Private/ADGroupVerify.ps1
function ADGroupVerify { <# .SYNOPSIS Find a group (by CN) in multiple domains and return *all* members using pure ADSI range-retrieval. .PARAMETER GroupName Group common name (CN). .PARAMETER Domains DNS domains to search, e.g. @("lab.company.com","test.company.com"). .OUTPUTS PSCustomObject { Domain ; Members } – one per domain where the group exists. If group not found anywhere, writes a message. #> param( [Parameter(Mandatory)][string] $GroupName, [Parameter(Mandatory)][string[]] $Domains ) $escapedCN = $GroupName -replace '([\\*()\0])', { '\{0:x2}' -f [byte][char]$args[0].Value } $groupFilter = "(&(objectClass=group)(cn=$escapedCN))" $found = $false foreach ($domain in $Domains) { try { # Build "DC=x,DC=y" path for the GC of this domain $dcParts = $domain -split '\.' | ForEach-Object { "DC=$_" } $dcPath = $dcParts -join ',' $gcRoot = [ADSI]"GC://$dcPath" $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.SearchRoot = $gcRoot $searcher.SearchScope = 'Subtree' $searcher.PageSize = 100 $searcher.Filter = $groupFilter $searcher.PropertiesToLoad.Add('distinguishedName') | Out-Null # ---- locate the group object first ---- $grp = $searcher.FindOne() if (-not $grp) { continue } # not in this domain $found = $true $members = @() # ---- dynamic range retrieval loop ---- $rangeStart = 0 $rangeSize = 1500 # AD’s hard limit per chunk while ($true) { $rangeAttr = "member;range=$rangeStart-*" $searcher.PropertiesToLoad.Clear() $searcher.PropertiesToLoad.Add($rangeAttr) | Out-Null $chunk = $searcher.FindOne() if (-not $chunk) { break } # The server returns the *actual* attribute name containing the numbers $attrName = $chunk.Properties.PropertyNames | Where-Object { $_ -like "member;range=$rangeStart-*" } if (-not $attrName) { break } # nothing else $members += $chunk.Properties[$attrName] if ($attrName -match 'member;range=\d+-(\d+|\*)$') { $endVal = $Matches[1] if ($endVal -eq '*') { break # last chunk received } else { $rangeStart = [int]$endVal + 1 # next chunk start } } else { break } } [pscustomobject]@{ Domain = $domain Members = $members Membercount = $members.Count } } catch { Write-Warning "Error searching $domain : $($_.Exception.Message)" } } if (-not $found) { Write-Output "Group '$GroupName' not found in any supplied domain." } } |