# PSEnumLargeGroup.ps1 # PowerShell program to enumerate the members of a large Active # Directory group. # # ---------------------------------------------------------------------- # Copyright (c) 2011 Richard L. Mueller # Hilltop Lab web site - http://www.rlmueller.net # Version 1.0 - November 28, 2011 # # This program retrieves all direct members of any Active Directory # group, even if there are more than 1500 members. The program uses # ADO and range retrieval. # # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. # Read group sAMAccountName from the command line or prompt for value. Param ($Group) If ($Group -eq $Null) { $Group = Read-Host "Enter group ""pre-Windows 2000"" name" } # Use ADO to search entire domain. $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() $Root = $Domain.GetDirectoryEntry() $adoConnection = New-Object -comObject "ADODB.Connection" $adoCommand = New-Object -comObject "ADODB.Command" $adoConnection.Open("Provider=ADsDSOObject;") $adoCommand.ActiveConnection = $adoConnection $adoCommand.Properties.Item("Page Size") = 200 $adoCommand.Properties.Item("Timeout") = 30 $adoCommand.Properties.Item("Cache Results") = $False $Base = $Root.distinguishedName $Scope = "subtree" $Filter = "(&(objectCategory=group)(sAMAccountName=$Group))" # Setup range limits. $Last = $False $RangeStep = 999 $LowRange = 0 $HighRange = $LowRange + $RangeStep $Total = 0 $ExitFlag = $False Do { If ($Last -eq $True) { # Retrieve remaining members (less than 1000). $Attributes = "member;range=$LowRange-*" } Else { # Retrieve 1000 members. $Attributes = "member;range=$LowRange-$HighRange" } $Query = ";$Filter;$Attributes;$Scope" $adoCommand.CommandText = $Query $adoRecordset = $adoCommand.Execute() $Count = 0 $Members = $adoRecordset.Fields.Item("$Attributes").Value If ($Members -eq $Null) { "Group $Group not found" $Last = $True } Else { # If $Members is not an array, no members were retrieved. If ($Members.GetType().Name -eq "Object[]") { ForEach ($Member In $Members) { # Output the distinguished name of each direct member of the group. $Member $Count = $Count + 1 } } } $adoRecordset.Close() $Total = $Total + $Count # If this is the last query, exit the Do loop. If ($Last -eq $True) {$ExitFlag = $True} Else { # If the previous query returned no members, the query failed. # Perform one more query to retrieve remaining members (less than 1000). If ($Count -eq 0) {$Last = $True} Else { # Retrieve the next 1000 members. $LowRange = $HighRange + 1 $HighRange = $LowRange + $RangeStep } } } Until ($ExitFlag -eq $True) $adoConnection.Close() "Total: $Total"