1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <###################################################### ## ## ## Recursive Group Membership Script ## ## ## ## Uses Get-DistributionGroupMember cmdlet without ## ## having to install Quest tools, only EXCH Snapin ## ## ## ## Author .................... Christopher Law ## ## Date ...................... 10/10/2012 ## ## Verison ................... 1.0 ## ## Rev Notes ................. None ## ## ## #######################################################> ## Install Excahnge Snapin Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue; #2010 ## Clear the screen cls ## Set Variables: $group = "#Every Employee (NC)" $members = New-Object System.Collections.ArrayList ## Create the Function function getMembership($group) { $searchGroup = Get-DistributionGroupMember $group -ResultSize Unlimited foreach ($member in $searchGroup) { if ($member.RecipientTypeDetails-match "Group" -and $member.DisplayName -ne "") { getMembership($member.DisplayName) } else { if ($member.DisplayName -ne "") { if (! $members.Contains($member.DisplayName) ) { $members.Add($member.DisplayName) >$null } } } } } ## Run the function getMembership($group) ## Output results to screen $members.GetEnumerator() | sort-object |
Get Recursive Group Membership of Distribution Group (PowerShell)
I spent part of the day yesterday looking for a good way to dump members/users of a Distribution group. No big deal except this situation has many levels of nested groups. There’s a Quest (Dell) PowerShell snapin that will do this, but why install anything else on a production server that doesn’t need to be there? I did, however, find an article for Exchange 2007 that did something like this, but when using it for 2010 it didn’t work for my needs. I just needed something simple that would work with Exchange 2010 and would run “out of box” on the server… Here’s what I came up with:
This is great, but how can I add the ability to get the member’s email addresses?
Just change:
$members.Add($member.DisplayName)
to
$members.Add([string]$member.PrimarySmtpAddress)
or you could combine them:
$members.Add($("$($member.DisplayName) ($([string]$member.PrimarySmtpAddress))"))
or were you looking to store both in the array/hashtable?
I found it was easier to just export all of the values to a CSV.
Changed
$members.Add($member.DisplayName)
to
$members.Add($member)
and then at the end of the script I ran
$members | Export-Csv all_members_mailing_list.csv
From there you can grab whatever you want.
Hi Christopher,
I am running this against a group that likely has 6,000+ members. It has a TON of nested upon nested groups.
When I run the script, I get the following:
The script failed due to call depth overflow. The call depth reached 1001 and the maximum is 1000.
Any ideas?
Thanks,
Brian
If you run it with PS 3, your limitation is memory on the machine you run it on. PS 2 has a max limit of 1000. If PS 3 isn’t an option, then I think a separated function would be required to call another function, and return the results in the current function. I don’t really have groups that deep to test it on, so I would say try PS 3 first and see what happens.
Hi Christopher,
thats a great script but can to add a section to export the list to csv as well, Good Job.
just pipe the results:
Hi Christopher,
I just want express my thanks and let you know this works like a charm! It really helps a lot.
Cheers,
Tengfei
I am running this script for 1000+ distribution groups – I am looking for an option to display the Distribution group name first and then the members..
I am trying to pipe the results to a CSV file and not getting the results I need.
I have the following setup from the code above…
## Set Variables:
$group = “DL Group”
$members = New-Object System.Collections.ArrayList
## Create the Function
function getMembership($group) {
$searchGroup = Get-DistributionGroupMember $group -ResultSize Unlimited
foreach ($member in $searchGroup) {
if ($member.RecipientTypeDetails-match “Group” -and $member.DisplayName -ne “”) {
getMembership($member.DisplayName)
}
else {
if ($member.DisplayName -ne “”) {
if (! $members.Contains($member.DisplayName) ) {
$members.Add($(“$($member.DisplayName),$($member.FirstName),$($member.LastName),$($member.Title),$($member.Office),$($member.PrimarySmtpAddress)”)) >$null
}
}
}
}
}
## Run the function
getMembership($group)
## Output results to screen
$members.GetEnumerator() | sort-object
$members | Export-Csv C:\Scripts\Get-DLmembership\$group.csv
It seems that piping a hash table isn’t as simple as it sounds as all I’m getting in the csv file is
“#TYPE System.String”
“Length”
“88”
“84”
“100”
…an so on
The output on screen looks perfect so I’ve also tried piping that to a file without any joy…
$members.GetEnumerator() | sort-object | Export-Csv C:\Scripts\Get-DLmembership\$group.csv
Can anyone shed any light on how to pipe the results of a hash table to a file. I’ve searched the web but can’t seem to get the right syntax.
Nice and easy. Good job
Thanks,
Ive modified this to add more variables (for multiple distribution groups), and more functions (one for each distributio group) to grab the nested users from multiple groups, pipe them into a single $members array, and then run the following at the end to assign a service account send as permissions to their mailbox. Set as a scheduled task this is saving our service desk so much time. Great script!
foreach ($User in $members) {Add-ADPermission $User -User domain\serviceaccount.svc -Extendedrights “Send As”}