🔧 New: User Management Graph PowerShell Toolkit

Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.

🚀 Launch Toolkit

Export Administrative Units with Member Counts to CSV

When you’re auditing access or validating delegated administration, you often need more than just AU names—you need a quick sense of how many objects are scoped inside each AU. This script exports every AU along with a MemberCount to a CSV. The file is perfect for audit trails, RBAC reviews, capacity planning, and governance reports where the AU Id and member totals are crucial.


The Script

# Connect to Microsoft Graph (run once per session)
Connect-MgGraph -Scopes "AdministrativeUnit.Read.All","Directory.Read.All"
# Output path (timestamped to avoid overwrites)
$OutputPath = ".\AdministrativeUnits_WithMemberCounts_{0}.csv" -f (Get-Date -Format "yyyyMMdd_HHmmss")
                                
# Get all AUs with key properties
$aus = Get-MgDirectoryAdministrativeUnit -All -Property Id,DisplayName,Description
                                
if (-not $aus) {
    Write-Warning "No Administrative Units were found in the tenant."
    $aus = @()
}
                                
# Build rows with a MemberCount column
$rows = @()
$total = ($aus | Measure-Object).Count
$index = 0
                                
foreach ($au in $aus) {
    $index++
    Write-Progress -Activity "Counting AU members" -Status "AU $index of $total" -PercentComplete (($index/$total)*100)
                                
    # Count members (users/devices/groups) for the AU
    $memberCount = $null
    try {
        $memberCount = (Get-MgDirectoryAdministrativeUnitMember `
        -AdministrativeUnitId $au.Id -All -Property Id -ConsistencyLevel eventual | Measure-Object).Count
    } catch {
        Write-Warning "Could not count members for AU '$($au.DisplayName)' ($($au.Id)): $($_.Exception.Message)"
        $memberCount = $null
    }
                                
    $rows += [pscustomobject]@{
    Id          = $au.Id
        DisplayName = $au.DisplayName
        Description = $au.Description
        MemberCount = $memberCount
    }
}

# Export to CSV (UTF-8)
$rows | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8

Write-Host "Export complete: $OutputPath  (AUs: $($rows.Count))"
                            


How the Script Works

  1. Connects to Graph using AdministrativeUnit.Read.All (and Directory.Read.All) and sets the stable v1.0 profile.
  2. Retrieves all AUs with -All and limits properties to Id, DisplayName, Description for speed.
  3. Counts members per AU using Get-MgDirectoryAdministrativeUnitMember -All and Measure-Object. The script adds the count as MemberCount.
  4. Exports to CSV with UTF-8 encoding and a timestamped file name to keep runs separate.

Further Enhancements

  • Add Filters/Search to narrow scope
  • # Filter by name prefix

    $aus = Get-MgDirectoryAdministrativeUnit -Filter "startswith(displayName,'EMEA')" -ConsistencyLevel eventual -All -Property Id,DisplayName,Description

    # Search by keyword

    $aus = Get-MgDirectoryAdministrativeUnit -Search '"marketing"' -ConsistencyLevel eventual -All -Property Id,DisplayName,Description
  • Per-type counts (user/group/device)
  • Replace the single MemberCount with simple post-processing by inspecting @odata.type from Get-MgDirectoryAdministrativeUnitMember and tallying into UserCount, GroupCount, DeviceCount.

  • Performance tips for large tenants
    • Run during off-peak hours.
    • If you move to PowerShell 7+, consider ForEach-Object -Parallel with caution and a small -ThrottleLimit to avoid throttling.
  • Alternate outputs
  • Create a JSON alongside the CSV:

    $rows | ConvertTo-Json -Depth 6 | Out-File ($OutputPath -replace '\.csv$','.json') -Encoding utf8

Possible Errors & Solutions

Error Cause Solution
Authorization_RequestDenied / Insufficient privileges Missing Graph permission/consent. Connect with AdministrativeUnit.Read.All (or Directory.Read.All), consent when prompted, then re-run the script.
Request_UnsupportedQuery (with -Filter/-Search) Unsupported property or malformed OData, or search not enabled for that field. Use filterable props like displayName. Keep filters simple (eq, startswith). For broad matching use -Search '"term"' and add -ConsistencyLevel eventual.
ResourceNotFound / 404 while counting members AU Id is wrong or the AU was deleted mid-run. Re-list AUs to confirm the Id, then re-run.
TooManyRequests / 429 throttling Rapid per-AU member calls. Re-run at off-peak, pause between iterations (e.g., Start-Sleep -Seconds 1), or reduce any parallelism if you added it.
Empty/Null MemberCount for some AUs Transient API issues or access limitations on specific objects. Re-run the script; if persistent, verify permissions and try on a smaller subset using -Filter to isolate.

Conclusion

This no-functions script produces a clean CSV with AU Ids, names, descriptions, and member counts—exactly what admins need for audits, RBAC reviews, and governance. It’s easy to read, easy to run, and simple to extend with filters, per-type counts, or alternate output formats.


Graph PowerShell Explorer Widget

20 Graph PowerShell cmdlets with easily accessible "working" examples.


Permission Required

Example:


                


                


                

© m365corner.com. All Rights Reserved. Design by HTML Codex