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:


    1. 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?

      1. 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.

  1. 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?


    1. 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.

  2. Hi Christopher,

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


  3. 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..

  4. 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.

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

Leave a comment

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