Script repository

Group membership of user subordinates

Updated on: Jan 18, 2026, Views: 1513

Reports, Group membership

The script generates a report containing subordinates of the selected user and the groups the subordinates are members of. Each subordinate will be added to the report the number of times matching the number of groups they are members of. To execute the script, create a report with a custom column of the Directory object type. The report scope should include subordinates of a user.

In the script, the $groupColumnID specifies the identifier of the custom column that will contain a group a subordinate is a members of. To get the identifier:

  • In the Report-specific columns section, on the Columns tab, right-click the custom column.
  • In the context menu, navigate to Copy and click Column ID.
  • The column identifier will be copied to clipboard.
$groupColumnID = "{3345fe9c-9c7d-43ab-9aee-92fb041d9091}" # TODO: modify me

$criteria = New-AdmCriteria "*"
$Context.DirectorySearcher.AddCriteria($criteria)

# Create a hash table to map group GUIDs to search results.
$guidComparer = $Context.CreatePropertyValueComparer("objectGuid")
$groupGuidToDN = New-Object System.Collections.Hashtable @($guidComparer)

try
{
    $searchIterator = $Context.DirectorySearcher.ExecuteSearch()
    while ($Context.MoveNext($searchIterator))
    {
        $searchResult = $searchIterator.Current
        
        # Get GUIDs of the groups.
        $user = $Context.BindToObjectBySearchResult($searchResult)
        $groupGuidsBytes = $user.GetEx("adm-MemberOfGuid")
        
        $guidsToSearch = $NULL
        # Add already found objects
        foreach ($groupGuidBytes in $groupGuidsBytes)
        {
            if (-not $groupGuidToDN.Contains($groupGuidBytes))
            {
                if ($NULL -eq $guidsToSearch)
                {
                    $guidsToSearch = New-Object System.Collections.ArrayList
                }
                $guidsToSearch.Add($groupGuidBytes)
            }
            else
            {
                $groupDN = $groupGuidToDN[@(,$groupGuidBytes)][0]
                $clonedSearchResult = $searchResult.Clone($False)
                $columnValues = @{ $groupColumnID = $groupDN; }
                $Context.Items.Add($clonedSearchResult, $columnValues, $NULL)
            }
        }
        
        if ($NULL -eq $guidsToSearch)
        {
            continue
        }
        
        # Search for groups
        $groupSearcher = $Context.CreateGuidBasedSearcher($guidsToSearch)
        $groupSearcher.SetPropertiesToLoad(@("distinguishedName", "objectGuid"))
        try
        {
            $groupSearchIterator = $groupSearcher.ExecuteSearch()
            while ($Context.MoveNext($groupSearchIterator))
            {
                $groupSearchResult = $groupSearchIterator.Current
                
                # Remember the group DN
                $groupGuid = $groupSearchResult.GetPropertyByName("objectGuid").Values[0]
                $groupDN = $groupSearchResult.GetPropertyByName("distinguishedName").Values[0]
                $groupGuidToDN[$groupGuid] = $groupDN
    
                # Add the object to the report
                $clonedSearchResult = $searchResult.Clone($False)
                $columnValues = @{ $groupColumnID = $groupDN; }
                $Context.Items.Add($clonedSearchResult, $columnValues, $NULL)
            }
        }
        finally
        {
            if ($groupSearchIterator) { $groupSearchIterator.Dispose() }
        }
    }
}
finally
{
    if ($searchIterator) { $searchIterator.Dispose() }
}

Comments 0

You must be signed in to comment.

    Got questions?

    Support Questions & Answers

    We use cookies to improve your experience.
    By your continued use of this site you accept such use.
    For more details please see our privacy policy and cookies policy.