Public/get-groupmembers.ps1
|
# get-groupmembers.ps1 # Lists all members of a group. Useful for auditing distribution lists, # security groups, and M365 groups. # Requires: Graph (Group.Read.All, User.Read.All) if (-not (Get-MgContext)) { Connect-MgGraph -Scopes "Group.Read.All", "User.Read.All" -ContextScope Process } $groupName = Read-Host "Enter group display name (exact match)" $group = Get-MgGroup -Filter "displayName eq '$groupName'" if (-not $group) { Write-Host "Group not found: $groupName" -ForegroundColor Red; exit } if ($group.Count -gt 1) { Write-Host "Multiple matches — be more specific." -ForegroundColor Red; exit } Write-Host "`nGroup: $($group.DisplayName)" Write-Host "Type: $($group.GroupTypes -join ', ') | Mail: $($group.MailEnabled) | Security: $($group.SecurityEnabled)`n" $members = Get-MgGroupMember -GroupId $group.Id -All if ($members.Count -eq 0) { Write-Host "No members." } else { $results = foreach ($m in $members) { try { $u = Get-MgUser -UserId $m.Id -Property "DisplayName,UserPrincipalName" -ErrorAction Stop [PSCustomObject]@{ "Display Name" = $u.DisplayName "UPN" = $u.UserPrincipalName } } catch { [PSCustomObject]@{ "Display Name" = $m.Id "UPN" = "(non-user object)" } } } $results | Sort-Object "Display Name" | Format-Table -AutoSize $export = (Read-Host "Export to CSV? (y/n)") -eq "y" if ($export) { $safe = $groupName -replace '[\\/:*?"<>|]', '_' $path = "$env:USERPROFILE\Desktop\Group_${safe}_$(Get-Date -Format 'yyyyMMdd').csv" $results | Export-Csv -Path $path -NoTypeInformation Write-Host "Exported to $path" } } |