Exchange Server TechCenter > Exchange Server Forums > Admin > Powershell command to list all distribution groups and members of those groups.
Ask a questionAsk a question
 

AnswerPowershell command to list all distribution groups and members of those groups.

  • Monday, November 02, 2009 9:59 PMmwatts7055 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I have been tasked with listing all of the distribution groups in our org and showing all members of every group.

    I have tired using get-distributiongroup | get-distributiongroupmember

    But it only show the members and not the groups.  Any scripters out there got a quick one liner I could use?  I really don't want to have to go through all 200 distribution groups manually exporting members to a .csv for each group.

    Thanks in advance!

Answers

  • Tuesday, November 03, 2009 3:24 PMKarl Mitschke Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    This is my script:

    usage :
    get-exgrouprecurse <groupname> will display group members and the subgroup on screen

    $group = get-exgrouprecurse <groupname>
    $group |Export-Csv <file name> -NoTypeInformation will export the group members to a file

    #####################################
    #                                   #
    # Script to retreive group members  #  
    #                                   #
    #    Karl Mitschke March 7 2008     #
    #                                   #
    #####################################
    
    ######################################
    #  heavily modified from recipe 7.3  # 
    #   in 'Active Directory Cookbook'   #
    #          by Robbie Allen           #
    ######################################
    
    #requires -pssnapin Microsoft.Exchange.Management.PowerShell.Admin
    param($group)
    $UnknownGroup = @{}
    function DisplayMembers($group)
    {
    	$SubGroup = @{}
    	$AllMembers = @()
    	if(!$group)
    	{
    		$group = Read-Host "Enter the groups display name"
    	}
    	if ($group.Contains("'"))
    	{
    		$group = $group.Replace("'",'"')
    	}
    	if ($group -eq "/?")
    	{
    		Write-Host "Usage:"
    		Write-Host ""
    		Write-Host "get-exgrouprecurse -group <group name>"
    		Write-Host ""
    		Write-Host "or get-exgrouprecurse <group name>"
    		Write-Host "Returns an object containing the group member, and the group name."
    		break
    	}
    	
    	$validate = Get-Group $group
    	if ($validate.RecipientTypeDetails.ToString() -match "mail")
    	{
    		$searchGroup = Get-DistributionGroupMember $group
    		if ($searchGroup)
    		{	
    			foreach ($member in $searchGroup)
    			{
    				$membertype = $member.RecipientTypeDetails
    				if($membertype -match "Group")
    				{
    					$samname = $member.SamAccountName.ToString()
    					if ($SubGroup.ContainsKey($samname) -eq $true)
    					{
     						Write-Output "^ already seen group member (stopping to avoid loop)"
    					}
    		         	else
    					{
    						$SubGroup.Add($samname,$member.DisplayName.ToString())
    					}
    				}	
    				else
    				{
    					if($member.PrimarySmtpAddress -and $member.RecipientTypeDetails -notcontains "group")
    					{
    						$obj = new-object psObject
    						$obj | Add-Member -membertype noteproperty -name GroupMember -Value $member
    						$obj | Add-Member -MemberType noteproperty -Name GroupName -Value $group
    						$AllMembers += $obj
    					}					
    				}
    			}
    		}
    		else
    		{
    			$UnknownGroup.add($group,1)
    		}
    		if($SubGroup.Values.Count -gt 0)
    		{
    			foreach ($subGroup in $SubGroup.values)
    			{
    				DisplayMembers $subGroup
    			}
    		}
    		if ($UnknownGroup.Keys.Count -gt 0)
    		{
    			foreach ($LostGroup in $UnknownGroup.keys)
    			{
    				$obj = new-object psObject
    				$obj | Add-Member -membertype noteproperty -name GroupMember -Value "Cannot enumerate group"
    				$obj | Add-Member -MemberType noteproperty -Name GroupName -Value $LostGroup
    				$AllMembers += $obj
    			}
    			$UnknownGroup.Clear()
    		}	
    	}	
    	else
    	{
    		Write-Output "$group does not appear to be mail enabled."
    	}
    	Write-Output $AllMembers 
    }
    DisplayMembers $group
    

  • Wednesday, November 04, 2009 3:09 PMJon-Alfred Smith Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    This works on my SBS 2008 box. Nice if anybody out there could test the script as well. There are some quirks with PowerShell v1 (and my thinking). You can easily add a Write-Host $_ before the For loop and Write-Host $member inside the For loop to get screen output or just see what is going on.  

     

    # Initialize array with two fields:

    # Distribution group, Members

    $totalObj = @()

     

    # Retrieve all DGs

    $temp = Get-DistributionGroup -ResultSize Unlimited | 

          

           # Loop through all distribution groups

           ForEach-Object {          

          

                 # Add the members of the DG to an array

                 [array]$mem = Get-DistributionGroupMember -id $_     

                

                 # Loop through the DG and assign each member name to the variable $member

                 for ($i = 0; $i -lt $mem.Count; $i++) {

                        $member = $mem[$i].name

                       

                        # Create instance of object of type .NET

                        $obj = New-Object System.Object

          

                        # Add the name of the DG to the object

                        $obj | Add-Member -MemberType NoteProperty -Value $_.Name -Name 'Distribution Group' -Force

                       

                        # Add the member name to the object

                        $obj | Add-Member -MemberType NoteProperty -Value $member -Name 'Members' -Force -PassThru

                       

                        # Add the object to the array

                        $totalObj += $obj

                 }

           }

     

    # Pipe output to .csv file

    $totalObj | Export-Csv -Encoding 'Unicode' c:\temp\ngtest.csv

     

    The output is written like this to the csv. file:

     

    "Distribution Group",Members

    "All Users","Jon-Alfred Smith"

    "All Users","Julie Smith"

    "Windows SBS Administrators","Standard User with administration links"

    "Windows SBS Administrators","Jon-Alfred Smith"

    If you just want to have the name of the DG once, change this line: Only add the name the first time, when the counter is zero:

     

    # Add the name of the DG to the object

    if ($i -eq 0) {

    $obj | Add-Member -MemberType NoteProperty -Value $_.Name -Name 'Distribution Group' -Force

    }

     



    MCTS: Messaging | MCSE: S+M | Small Business Specialist     

All Replies

  • Monday, November 02, 2009 11:09 PMKarl Mitschke Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    If you use Quest Free PowerShell Commands for Active Directory you can do a:

    Get-QadGroup -GroupType "Distribution" | Get-QadGroupMember -Indirect

    http://www.quest.com/powershell/activeroles-server.aspx

    In EMS it's harder, but I can post a script if you'd like,

    Karl
  • Tuesday, November 03, 2009 1:49 AMmwatts7055 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I have seen the Quest Free PowerShell Commands but we are not using them.  If you wouldn't mind I would really appreciate it if you could post your script.  I would like to see how this works natively in EMS.

    Thank you
  • Tuesday, November 03, 2009 2:23 AMNitin Gupta [gupnit]MVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    Does this help....

    $DGrps = Get-DistributionGroup
    ForEach ($DGrp in $DGrps) {Write-Host DGrp.name -Filepath <yourfilename> -append $GrpMbrs = Get-DistributionGroupMember -id $DGrp
    foreach ($GrpMbr in $GrpMbrs) {Write-Host $GrpMbr.DistinguishedName -Filepath <yourfilename> -append }}


    Nitin Gupta (gupnit) | MVP - Exchange | http://www.nitingupta.in/blogs
  • Tuesday, November 03, 2009 3:12 PMmwatts7055 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    This does appear to work but how do I go about outputting the file to somewhere?  I entered C:\data.csv for <yourfilename> but never see the file created and when I create a blank file called C:\data.csv hoping that the data will append to the file it remains empty.

    Thank for your help!
  • Tuesday, November 03, 2009 3:24 PMKarl Mitschke Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    This is my script:

    usage :
    get-exgrouprecurse <groupname> will display group members and the subgroup on screen

    $group = get-exgrouprecurse <groupname>
    $group |Export-Csv <file name> -NoTypeInformation will export the group members to a file

    #####################################
    #                                   #
    # Script to retreive group members  #  
    #                                   #
    #    Karl Mitschke March 7 2008     #
    #                                   #
    #####################################
    
    ######################################
    #  heavily modified from recipe 7.3  # 
    #   in 'Active Directory Cookbook'   #
    #          by Robbie Allen           #
    ######################################
    
    #requires -pssnapin Microsoft.Exchange.Management.PowerShell.Admin
    param($group)
    $UnknownGroup = @{}
    function DisplayMembers($group)
    {
    	$SubGroup = @{}
    	$AllMembers = @()
    	if(!$group)
    	{
    		$group = Read-Host "Enter the groups display name"
    	}
    	if ($group.Contains("'"))
    	{
    		$group = $group.Replace("'",'"')
    	}
    	if ($group -eq "/?")
    	{
    		Write-Host "Usage:"
    		Write-Host ""
    		Write-Host "get-exgrouprecurse -group <group name>"
    		Write-Host ""
    		Write-Host "or get-exgrouprecurse <group name>"
    		Write-Host "Returns an object containing the group member, and the group name."
    		break
    	}
    	
    	$validate = Get-Group $group
    	if ($validate.RecipientTypeDetails.ToString() -match "mail")
    	{
    		$searchGroup = Get-DistributionGroupMember $group
    		if ($searchGroup)
    		{	
    			foreach ($member in $searchGroup)
    			{
    				$membertype = $member.RecipientTypeDetails
    				if($membertype -match "Group")
    				{
    					$samname = $member.SamAccountName.ToString()
    					if ($SubGroup.ContainsKey($samname) -eq $true)
    					{
     						Write-Output "^ already seen group member (stopping to avoid loop)"
    					}
    		         	else
    					{
    						$SubGroup.Add($samname,$member.DisplayName.ToString())
    					}
    				}	
    				else
    				{
    					if($member.PrimarySmtpAddress -and $member.RecipientTypeDetails -notcontains "group")
    					{
    						$obj = new-object psObject
    						$obj | Add-Member -membertype noteproperty -name GroupMember -Value $member
    						$obj | Add-Member -MemberType noteproperty -Name GroupName -Value $group
    						$AllMembers += $obj
    					}					
    				}
    			}
    		}
    		else
    		{
    			$UnknownGroup.add($group,1)
    		}
    		if($SubGroup.Values.Count -gt 0)
    		{
    			foreach ($subGroup in $SubGroup.values)
    			{
    				DisplayMembers $subGroup
    			}
    		}
    		if ($UnknownGroup.Keys.Count -gt 0)
    		{
    			foreach ($LostGroup in $UnknownGroup.keys)
    			{
    				$obj = new-object psObject
    				$obj | Add-Member -membertype noteproperty -name GroupMember -Value "Cannot enumerate group"
    				$obj | Add-Member -MemberType noteproperty -Name GroupName -Value $LostGroup
    				$AllMembers += $obj
    			}
    			$UnknownGroup.Clear()
    		}	
    	}	
    	else
    	{
    		Write-Output "$group does not appear to be mail enabled."
    	}
    	Write-Output $AllMembers 
    }
    DisplayMembers $group
    

  • Tuesday, November 03, 2009 6:36 PMmwatts7055 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks for posting your script Karl. 

    In less I am doing something wrong the script still asks that I submit the anme of the group I want to know about.  I need to know this information for all DL Groups at one time.  Is there away to tell the script to give me information about all of my groups?

    Thank you
  • Tuesday, November 03, 2009 8:56 PMKarl Mitschke Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Try this:

    Get-DistributionGroup -ResultSize unlimited |%{.\get-exgrouprecurse $_.Name}

    I am pretty sure this will not show the name of the main group - like:

    Group A
    has a member  member 1
    and a member Sub Group 1
    Which has a member Member 2

    I could modify it at some point, or perhaps you can follow it and modify it.

    Karl
  • Wednesday, November 04, 2009 12:25 AMDan Holton Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    At a quick glance, Nitin's script should do what you're looking for with a few modifications.  Write-host is what's preventing the output from going to the file like you're trying to accomplish.  You can modify the script to use the re-directors, or just use out-file.  I haven't tested it, but this should work (just fixing a few bits from Nitin's script, but other then that, really just a copy and paste of his post.)

    $DGrps = Get-DistributionGroup
    ForEach ($DGrp in $DGrps) {out-file -inputobject $DGrp.name -Filepath <yourfilename> -append $GrpMbrs = Get-DistributionGroupMember -id $DGrp
    foreach ($GrpMbr in $GrpMbrs) {out-file -inputobject $GrpMbr.DistinguishedName -Filepath <yourfilename> -append }}


    Good luck,
    Dan Holton
  • Wednesday, November 04, 2009 2:56 AMNitin Gupta [gupnit]MVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks Mate....I have not tested it, I should have mentioned that, thought it should do the trick.
    Nitin Gupta (gupnit) | MVP - Exchange | http://www.nitingupta.in/blogs
  • Wednesday, November 04, 2009 3:09 PMJon-Alfred Smith Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    This works on my SBS 2008 box. Nice if anybody out there could test the script as well. There are some quirks with PowerShell v1 (and my thinking). You can easily add a Write-Host $_ before the For loop and Write-Host $member inside the For loop to get screen output or just see what is going on.  

     

    # Initialize array with two fields:

    # Distribution group, Members

    $totalObj = @()

     

    # Retrieve all DGs

    $temp = Get-DistributionGroup -ResultSize Unlimited | 

          

           # Loop through all distribution groups

           ForEach-Object {          

          

                 # Add the members of the DG to an array

                 [array]$mem = Get-DistributionGroupMember -id $_     

                

                 # Loop through the DG and assign each member name to the variable $member

                 for ($i = 0; $i -lt $mem.Count; $i++) {

                        $member = $mem[$i].name

                       

                        # Create instance of object of type .NET

                        $obj = New-Object System.Object

          

                        # Add the name of the DG to the object

                        $obj | Add-Member -MemberType NoteProperty -Value $_.Name -Name 'Distribution Group' -Force

                       

                        # Add the member name to the object

                        $obj | Add-Member -MemberType NoteProperty -Value $member -Name 'Members' -Force -PassThru

                       

                        # Add the object to the array

                        $totalObj += $obj

                 }

           }

     

    # Pipe output to .csv file

    $totalObj | Export-Csv -Encoding 'Unicode' c:\temp\ngtest.csv

     

    The output is written like this to the csv. file:

     

    "Distribution Group",Members

    "All Users","Jon-Alfred Smith"

    "All Users","Julie Smith"

    "Windows SBS Administrators","Standard User with administration links"

    "Windows SBS Administrators","Jon-Alfred Smith"

    If you just want to have the name of the DG once, change this line: Only add the name the first time, when the counter is zero:

     

    # Add the name of the DG to the object

    if ($i -eq 0) {

    $obj | Add-Member -MemberType NoteProperty -Value $_.Name -Name 'Distribution Group' -Force

    }

     



    MCTS: Messaging | MCSE: S+M | Small Business Specialist     

  • Tuesday, November 17, 2009 7:54 PMitzafugasi Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Jon-alfred:
    I was looking for a way on how to do this, and your script was exactly what i was looking for. Thanks!