The Quest Active Directory Cmdlets are very useful in getting AD group members. The only thing I was missing, was a -Recursive parameter. So I created this script.

You feed it AD Group Names as a parameter, and it will return a nice tree view of all members and subgroups and their members and so on. Finally, it returns a list of allunique members and their email addresses. You can easily modify the script to include other properties and export the ouput to a csv file.

I hope you like it.

Hugo

Get-MyGroupMembersRecursive (Rename to .ps1)

Tagged with:
 

63 Responses to Listing AD Group Members Recursively with Powershell

  1. Dale says:

    Very nice! Very clean output, easy to customize and read the code. Thanks!

    -Dale

  2. admin says:

    Hi Dale,
    Welcome to my site!
    I am glad you like it.
    (Spread the word ;) )
    Hugo

  3. [...] quite a challenge. But I did it! Inspired by my scripts Create a Directory Tree with Powershell and Listing AD Group Members Recursively with Powershell, I responded to a queation in the VI Toolkit Community: “Is it possible to recursively get [...]

    »crosslinked«

  4. Derek says:

    How would one go about getting Dynamic Distribution Groups to show up as well???

  5. Ray says:

    Hi,

    Would there be a way to reverse this so you could pass a user and it would enumerate through the groups they’re a member of?

    Cheers

  6. Andy says:

    That’s really neat – thanks!

  7. Robert says:

    Hi,

    nice script.
    The script worked, but after a reinstall of the computer.
    I have install powershell over Windows Updates and now I get no Value from $Group.Members.Length
    Any Idea?

    thx

  8. JoJoMonkeyMan says:

    Thanks Hugo. I support Exchange. Quite often, people want to audit the members of a group to see who is getting the email. for large groups with many nestings, this is a pain. Previously, I could try and looking at the message tracking logs from previous emails. that stinks. I could add the list to the Outlook To: line and expand each dlist. Very time consuming.

    I’ve used this script a few times now and I’m so grateful. Thanks!

    You wouldn’t have any thoughts on how to copy a group with its members. Of course the root group has many nested groups. I was planning on simply using the new-qadgroup tool with some of the logic you used here.

    • admin says:

      Hello JoJoMonkeyMan,
      Thanks so much for taking the time to comment on my website. I appreciate it.
      I’ll think about your question. I’ll have to test some things before I can answer you.
      Hugo

  9. JoJoMonkeyMan says:

    @admin

    If I figure it out, I’ll send it to you. Thanks

  10. RCAlmeida says:

    Great script! Keep up with the good job! Thanks!

  11. Baggio, says:

    Tnx for this script. I am new to Powershell, so could you please tell me how to view te members of one AD group. Where can I put the name of my group into your script? Tnx for the answer

  12. Baggio, says:

    I Changed the extension of the script to ListGroupMembers.ps1
    How do I execute? Within Powershell he won’t do it. I already installed
    AD extension…..

    Tnx for you quick answer

  13. seymour says:

    Really neat script. I like it. However, being new to scripting/Powershell, I am not sure how to handle the following: when I run this script against a distribution list that is 90-95% exteranl contacts, it does not display any of the external contacts. How can I see those external email addresses. I need this for a request to export these addresses to another user. Also, how can I reroute the output to a text file? Command line arguement/redirect such as >group.txt?

    thanks…

    • admin says:

      Thanks. As for your questions: I don’t know the answer to the first one off the top of my head. Exporting to a text file is easy: you can use the >group.txt just like in DOS, but you can also add the followinf to the last line of the script:
      | Out-File D:\groups.txt

  14. Roger Smith says:

    Great script. Saved me lot of time doing the same, as I had already wasted a day trying to figure this, and was not getting the results sorted properly, When I stumbled on this script, it definitely made my day. Great job, and kudos! Cheers RS.

  15. admin says:

    Thank you!
    Your comment just made my day.
    Hugo

  16. Marco says:

    Is it some how possible to use this script to export all groups with members like Get-MyGroupMembersRecursive *

    By the way I’am already very happy with this one.

  17. David says:

    For the command output, how do i get the full output to a text file. Redirecting the console output to a text file only gives me the last section of members and not the tree view. Simular deal if I add the | out-file option on the last line.

  18. Tommy says:

    Hi.

    I would also like to thank for this most excellent script. Also if anyone have found a neat and tidy way to pipe the output of the first part to a file, let me know?

    • admin says:

      Hi Tommy,
      Thanks for the compliment.
      Try this: remove the last 4 lines from the script and replace all occurances of Write-Host text with Out-File text -FilePath ‘d:\scripts\output.txt’ -Append
      Hugo

  19. Kevin says:

    I just love a script that works. Within 2 minutes of finding this post, your script gave me the data that I was looking for. Unfortunately since you did such a great job, I’m now going to have to spend some time looking at what else you’ve got up here. ;)

    Great work.

  20. Gabe says:

    Sorry if the question has been asked, but how do you pass the group name as an argument. I’m completely new to Powershell and this script will perform a need I have. If an example could be provided I will be extremely helpful.

  21. Gabe says:

    I figured it out.

  22. PSNOOB says:

    I have yet to find an answer to my dilema. I need to seach all users in a specific OU to see what groups they belong to. If theyare missing membership to a specific group I need to have it added. Here is what I have so far but I think i am a bit off the mark.
    $users = Get-QADUser -SearchRoot ‘OU=Enabled,OU=Users,OU=Partners,DC=xxx,DC=com’-MemberOf ‘Allpartners’
    $un = read-Host “User Name domain\username” # Your domain and username
    $pw = read-host “Enter password” -AsSecureString # Your Password
    connect-QADService -service ‘xxx.com’ -ConnectionAccount $un -ConnectionPassword $pw

    ForEach ($user in $Users) {Where-Object -FilterScript ($_.Memberof -ne ‘Allpartners’)} {
    add-QADGroupMember -identity “CN=AllPartners,OU=Groups,OU=Partners,DC=xxx,DC=com” -member $user
    Set-QADUser -Identity $user -ObjectAttributes @{primaryGroupID=@(222753)}
    Remove-QADGroupMember -Identity ‘Domain Users’ -Member $user
    }

  23. Jim C says:

    Hugo – you are a PS Rockstar – you just made my day, and if you are ever in the Phoenix area, let me know and I’ll get you all liquored up!

  24. Brian says:

    Couple of caveats:
    What if my group has spaces in its name “xxxx xx xxx” and is in another domain?

    I typically use “-service” and point to a DC in that domain.
    Thoughts?
    Brian

    • admin says:

      I think spaces should be no problem, but give it a try.
      Connecting to a different domain was not incorporated in the script, but should be simple to add to all the Get-QAD* cmdlets.
      Hugo

  25. Greg says:

    Got this error when running the script. Ideas??

    Cannot validate argument on parameter ‘Identity’. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
    At :line:26 char:25
    + $Object = Get-QADObject <<<< $DN

  26. Nancy Lambert says:

    Thanks for this script. Simple and effective. Made one edit for my purposes which displays the Group Name as it goes through the subgroups:

    added $Object.Name in the Write-Host line right before the Indent

  27. [...] Slick Powershell Script – Includes recursive functionality Tags: active directory, distribution list, Exchange 2003 Comments RSS feed [...]

  28. Mcdrummerman says:

    $ldap = “YOUR_LDAP_PATH_HERE”

    $de = new-object directoryservices.directoryentry(“LDAP://” + $ldap)
    $ds = new-object directoryservices.directorysearcher($de)

    #$ds.filter = ‘(&(samaccountname=*))’
    $rc = $ds.findall()

    foreach($person in $rc)
    {
    $entry = $person.getdirectoryentry()

    write-host “#################################################”
    write-host “@ ” $entry.name
    write-host “#################################################”
    write-host Group Membership `n——————

    foreach($groupName in $entry.memberof )
    {
    $g = $groupname.tostring(); $g.substring(3,$g.indexof(“,”)-3)
    #$groupname
    }

    write-host
    }

  29. Mcdrummerman says:

    Sorry had the filter set up wrong. It should now only find user objects. This will find all user objects under the given OU.

    ——————–

    $ldap = “LDAP_PATH_HERE”

    echo ” “;
    $de = new-object directoryservices.directoryentry(“LDAP://” + $ldap)
    $ds = new-object directoryservices.directorysearcher($de);

    $ds.filter = “(&(samaccountname=*))”
    $rc = $ds.findall();

    foreach($person in $rc)
    {
    $entry = $person.getdirectoryentry()

    echo “#################################################”
    echo “@ $entry.name”
    echo “#################################################”
    echo “Group Membership `n——————”

    foreach($groupName in $entry.memberof )
    {
    $g = $groupname.tostring(); $g.substring(3,$g.indexof(“,”)-3)
    #$groupname
    }

    echo ” ”
    }

  30. Mcdrummerman says:

    Sorry had the filter set up wrong. It should now only find user objects. This will find all user objects under the given OU.

    ————————————–

    $ldap = “LDAP_PATH_HERE”

    $account = read-host “Which user? ( * for all)”

    echo ” “;
    $de = new-object directoryservices.directoryentry(“LDAP://” + $ldap);
    $ds = new-object directoryservices.directorysearcher($de);

    #805306368 = useraccount type
    $ds.filter = “(&(samaccountname=” + $account + “)(samaccounttype=805306368))”;
    $rc = $ds.findall();

    foreach($person in $rc)
    {

    echo “#################################################”;
    “@ ” + $person.properties.name;
    echo “#################################################”;
    echo “Group Membership `n——————”;

    foreach($groupName in $person.properties.memberof )
    {

    if($groupname){
    $g = $groupname.tostring();
    $g.substring(3,$g.indexof(“,”)-3);
    #$groupname ;
    }
    }

    echo ” ”
    }

  31. Manoj says:

    I am looking for an experineced windows developer with good experince in developing cmdlets (Powershell) and SAN; appriciate if you can connect me to them; JOb is based out of Bellevue, WA

  32. Chris says:

    Hi,

    This is a great tool.

    Is there are way to get the output in alphabetical (ascending) order?

    Thanks,
    Chris

  33. angel says:

    Please i need help getting this to work, I need to list all the members of every distribution list. Please help!

  34. Shep says:

    Here is the error that was returned to me. What am I missing?

    PS C:\> .\get-mygroupmembersrecursive.ps1
    The term ‘Get-QADGroup’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:\get-mygroupmembersrecursive.ps1:54 char:29
    + $ParentGroup = Get-QADGroup <<<< -Name $ParentGroupName
    + CategoryInfo : ObjectNotFound: (Get-QADGroup:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

  35. Shep says:

    Ok figured out that I need to download Quest piece and run PS from there.

    Thanks!

  36. selder says:

    I’m trying to modify the script so it exports the members of a group to a CSV file.

    But I’m afraid I don’t know how, could someone post the code?

  37. Dave says:

    Sorry for such a lame post, but I am a total PS noob. You say “feed it AD Group Names as a parameter” – what is the syntax you are using? I have tried everyting I can think of (and it all ends in an error at line 54,
    “Object reference not set to an instance of an object.
    At :line:54 char:28
    + $ParentGroup = Get-QADGroup <<<< -Name $ParentGroupName

  38. Dan says:

    Is there any way to feed it an OU, and have it get all groups and members from withing that OU?

  39. Robert T. says:

    Hi Hugo,

    I tried your script on a large DL but it didn’t include contacts. Is there a way to include contacts and mail-enabled users as well? How about users, mail-enabled users and contacts in other domains as well?

    Thanks. I work for a non-profit that helps kids in poor neighborhoods get to and through college and we really appreciate your making this script available.

    Robert

  40. Thomas Ljunggren says:

    Hi

    Get-QADGroup : Cannot validate argument on parameter ‘Name’. The argument is null or empty.

    Error i got when running script?

    /T

  41. Royon says:

    Hi,
    I’ve just downloaded the script and when I run it, some ‘group Name’ are not reported in the result. Is there difference between Local Group, Domain Group and Universal Group ?
    I tryed to put all groups in first one, no effects.
    Thanks.

  42. Royon says:

    Hi,
    Do you have a new version of this script because, I can’see in result all Group ‘Name’. I think, the script made difference between universal, global an local group.
    I used it in 2003 AD sever.
    Thanks

  43. Pavel says:

    I have changed 31 line to display Subgroups
    highlight=” Write-Host (“{0}{1}” -f $Indent,$Object) -ForegroundColor “green” “

  44. Pavel says:

    I have changed 31 line to display Subgroups
    Write-Host (“{0}{1}” -f $Indent,$Object) -ForegroundColor “green”

  45. Maria says:

    Pavel,
    I need to Audit Shared folders for their permissions. However, I need to be able to see ALL of the child folders AND enumerate the active directory users within each group that has permission to a particular share. I would like to incorporate Get-MyGroupMembersRecursive.ps1 with the script on http://poshcode.org/1721 named Audit NTFS on Shares by DigitalAsylum. However, I am at a loss about how to feed the user group through the script. Would you be able to assist?
    Kindest regards,
    Maria

  46. Pavel says:

    I am not good in powershell as you want. I solved similar problem by this small script. It has been working quite long. Result in .txt file I opened by hand in excel.

    # START

    dir \\FileServer\Sharing\ -recurse | Where-Object { $_.PSIsContainer } |
    ForEach-Object {Get-Acl $_.FullName} |
    ForEach-Object { $_.Access `
    | Add-Member -Name PSPath -MemberType NoteProperty -Value $_.PSPath -PassThru `
    | Add-Member -Force -Name ToString -MemberType ScriptMethod -Value {“$($this
    .IdentityReference), $($this.AccessControlType), $($this.FileSystemRights)”} -PassThru
    } |
    Where-Object { $_.IsInherited -like “*False*” } |
    Format-Table -AutoSize | Out-File D:\Result.txt -encoding unicode

    # END

    The result include only non inherited permittions. You have to change name of server, sharing and path to result file.
    Best regards
    Pavel

  47. Frank says:

    I am attempting to run a variation of this script which will get list of distribution groups, get the name of the group and its members (names and email) for part of the body of an email. And then email to each Distribution goup an email. So far I can get the groups and export-csv to remove notypeinformation and then clean up the quotes due to the export. I have part of the send-mailmessage crafted but having trouble putting all together especially getting group members per group…

    Any help would be appreciated… Thx

  48. mimola says:

    I run this script, but I don’t know what I change next row.

    $ParentGroup = Get-QADGroup -Name $ParentGroupName

    Next error message:

    Get-QADGroup : Cannot validate argument on parameter ‘Name’. The argument is null or empty. S………

  49. Magnus says:

    This script is great. I have a few trees in our AD Forest, how can I get the members of groups in the different domains. For example I have a list of Domain Groups (i.e. DomainA\Group1
    DOmainB\Group3 …etc

    I would liek to pull the sub groups and members from those as well. Any Ideas?

    Thanks
    Magnus

  50. Yarno Muzag says:

    Nice script, exactly what I think I need. Only, I don’t know how to use it. How do I get the actual group names into the param field (via a text file with a bunch of group names?) and where does the output go? How do I get the result into a csv or txt file?

Leave a Reply