如何让基于ADSI的PowerShell AD组成员获取函数支持递归?
实现AD组成员递归查询的PowerShell函数修改方案
现有一段PowerShell代码用于获取AD组成员并填充CSV,但不支持递归,无法获取嵌套安全组内的成员,请问如何修改使其支持递归?
原代码如下:
function getGroupMembers($groupName){ #get the group $group = [adsi]$("LDAP://$($groupName)") #set the initial from value $from = 0 #escape trigger when the $ds.findall() errors $all = $false #array for the members of the group $members = @() while (! $all) { #catch an error and set all to $true to escape trap{$script:all = $True;continue} #top end of the range so initally 0-999. a Range of 1000 is used to make sure it works on all versions of AD $to = $from + 999 #Query the group object for members using "member;range=$from-$to" to just return the range of objects for this pass. #This will generate an error with an invalid range $DS = New-Object DirectoryServices.DirectorySearcher($Group,"(objectClass=*)","member;range=$from-$to",'Base') $allResult = $ds.findOne() #as the variable name for the group name is not member, but member;range=0-999 etc, the $_.PropertyNames -like 'member;*' catches all instances $members += $allResult.properties | foreach {$_.item($_.PropertyNames -like 'member;*')} $all = $allResult.properties["member;range=$from-*"].Count -gt 0 #set up the next search range $from += 1000 } $members }
修改后的递归版本代码
function getGroupMembers($groupName, [ref]$processedGroups) { # 初始化已处理组集合,避免循环引用 if (-not $processedGroups.Value) { $processedGroups.Value = [System.Collections.Generic.HashSet[string]]::new() } # 若当前组已处理过,直接返回空,防止无限递归 if (-not $processedGroups.Value.Add($groupName)) { return @() } # 获取目标组对象 $group = [adsi]"LDAP://$groupName" $from = 0 $all = $false $members = @() while (-not $all) { trap{ $script:all = $true continue } $to = $from + 999 $DS = New-Object DirectoryServices.DirectorySearcher($Group,"(objectClass=*)","member;range=$from-$to",'Base') $allResult = $ds.findOne() $currentMembers = $allResult.properties | foreach {$_.item($_.PropertyNames -like 'member;*')} foreach ($member in $currentMembers) { # 获取成员的AD对象 $memberObj = [adsi]"LDAP://$member" # 判断成员是否为组,是则递归查询其成员 if ($memberObj.objectClass -contains "group") { $members += getGroupMembers -groupName $member -processedGroups $processedGroups } else { # 非组成员直接加入结果集 $members += $member } } $all = $allResult.properties["member;range=$from-*"].Count -gt 0 $from += 1000 } $members } # 调用示例(需传入组的完整LDAP路径) # $allMembers = getGroupMembers -groupName "CN=TestGroup,OU=Groups,DC=domain,DC=com" -processedGroups ([ref]$null)
修改说明
- 新增递归逻辑:遍历每个成员时,通过
objectClass属性判断是否为AD组,若是则递归调用函数获取嵌套成员。 - 防止循环引用:引入
[ref]$processedGroups参数,用哈希集合记录已处理的组,避免组互相嵌套导致的无限递归。 - 成员分类处理:区分普通成员(用户、计算机等)和组成员,仅对组执行递归操作,普通成员直接加入结果。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

