Exchange Information Technology Servers Tips, Tricks, & Tweaks

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:

12 replies on “Get Recursive Group Membership of Distribution Group (PowerShell)”

Just change:
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.


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?


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,

I just want express my thanks and let you know this works like a charm! It really helps a lot.


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 “”) {
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

## 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”
…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.


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”}

Leave a Reply

Your email address will not be published. Required fields are marked *