I have started setting up groups like:

  • Department-staff
    • Department-supervisors
      • Department-director

Where Department-supervisors is a member of Department-staff, and Department-director is a member of Department-supervisors.

I know how to use powershell to list what groups a person is a member of, either directly assigned, or inherited though the nested groups.

But what I'm trying to figure out is a script that will show me all the users who are members of one of those groups BOTH directly and indirectly, eg. User A is a direct member of Department-staff and Department-director.

My googling fails me in trying to find or write a script that can do that.


In reality, there are more layers and branches to the nesting, and many departments, so it gets confusing. I want to get a list of members who are part of any group directly, and also a member of the same group indirectly so I can remove the redundant group direct memberships.

  • If your users are only direct members of a single group (they shouldn't need multiple direct right?), then your list would be anyone who is not a direct member of Department-staff. Only members of Department-supervisors and Department-director would be members of both a direct group and an indirect, or two, group(s). – jscott May 22 '13 at 18:10
  • @jscott that sounds insightful...but I'm not quite following you...perhaps I need more coffee. – Grant May 22 '13 at 18:48

The following will walk a given parent group (name must be compatible with Get-ADGroupMember syntax) and populate two hashes. One hash will have user sAMAccountName as the key and a array of direct group memberships as the value. The second hash will contain keys of all processed groups.

It will correctly detect, and skip, circular group nestings (e.g. parent is child of child). You can comment out the Write-Host lines for less line noise in the console.

Import-Module ActiveDirectory

function Walk-Group ( $group ) {

    Get-ADGroupMember $group | Group-Object objectClass -ash | Foreach-Object {

        # Add each user to $users hash, add current group to their collection
        if ( $_.user ) {
            foreach ( $u in $_.user.GetEnumerator() ) {
                if ( $users[$u.sAMAccountName] ) {
                    $users[$u.sAMAccountName] += $group
                } else {
                    $users.Add( $u.sAMAccountName, @($group) )

        # Recurse into each child group, skip if group is circular member
        if ( $_.group ) {
            foreach ( $g in $_.group.GetEnumerator() ) {
                if ( $groups[$g.Name] ) {
                    Write-Host "Existing:" $g.Name
                } else {
                    Write-Host "New Group:" $g.Name
                    $groups.Add( $g.Name, $true )
                    Walk-Group $g.Name


# Hash to collect user/group info.
$users = @{}

# Hash to collect processed groups.
$groups = @{}

# Root group to walk
Walk-Group "Department-staff"

# Display users with mulitple direct memberships
$users.GetEnumerator() | Where-Object { $_.Value.Count -gt 1 }
  • Beautiful, that's exactly what I was looking for. Thanks so much! – Grant May 28 '13 at 12:53

EDIT: based on your updated description something like this should work. Note that I didn't take care of loops in group membership so you might find it running forever.

$RootGroup=Get-ADGroup "your group here" 
$username = "test user here"

Function RecurseMembership( $FromAbove, $username ) 

    $LevelUsers=$FromAbove | Get-ADGroupMember | where { $_.objectClass -eq "user" -and $_.SamAccountName -eq "$username" }
    $LevelGroups=$FromAbove | Get-ADGroupMember | where { $_.objectClass -eq "group" }

    $LevelGroups | ForEach-Object { RecurseMembership $_ $username } 


RecurseMembership $RootGroup $username 
  • Excellent site, and a very useful script, but doesn't do what I need. – Grant May 22 '13 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.