基于初始查询中的成员计数的 AD 组的 PowerShell 过滤(也就是不使用 -filter *)
PowerShell filtering for AD Groups based on Membership Count in the initial query (aka not using -filter *)
PowerShell 问题给各位精明的人。是否可以根据组大小过滤 Get-ADGroup
命令(也就是仅 return 组大于 x 成员)?我正在尝试以比以下更有效的方式进行过滤:
Get-ADGroup -Filter *
然后 运行 成员计数检查,如 | where {$_.members.count -gt 10,000}
或其他内容。
但是我很难对 初始过滤器 进行任何类型的成员计数检查,所以我不必 return 中的每个组对象个人域,然后检查成员数。这是因为我正在查询的 AD 实例有大量的 AD 组,需要很长时间才能先拉出所有组,然后再检查。
我已经尝试了下面的变体,但我猜测最初的“成员”属性 不存在于您可以查询的属性集中:
Get-ADGroup -Properties members -Filter {members -ge 10,000}
感谢任何帮助!
Is it possible to filter a Get-ADGroup command based on group size (aka only return groups greater than x members)?
没有!
Active Directory 支持的 LDAP 查询过滤器语法没有任何工具来指定 multi-valued 个属性的数量。
您需要在目录中查询具有 any 个成员的组,然后统计结果集 client-side:
Get-ADGroup -LDAPFilter '(&(objectClass=group)(member=*))' -Properties member |Where-Object {
$_.member.Count -gt 10000
}
这就是使用multi-threading提高查询速度的方法,在本例中使用Runspaces,主要思想是获取域中的所有OU,让每个运行空间查询同时一个特定的 OU(与 $threads
中定义的查询一样多)。
这应该可以大大提高脚本的速度,但是,这需要调整,如果同时有太多线程 运行很可能会失败。
$ErrorActionPreference = 'Stop'
# define the params that will be passed to the runspaces
$params = @{
LDAPFilter = "(member=*)"
SearchScope = 'OneLevel'
Properties = 'member'
}
# define the logic of the runspace
$scriptblock = {
param($params)
foreach($group in Get-ADGroup @params) {
if($group.Member.Count -gt 10000) {
$group
}
}
}
try {
# get all OUs
$ous = (Get-ADOrganizationalUnit -Filter *).DistinguishedName
# get all Domain Controllers available
# we don't want to make too many queries to the same DC!!
$dcs = (Get-ADDomainController -Filter *).Name
# define the number of threads that can run at the same time
# maybe you could use `$dcs.Count` as Threads
# this depends on your server's resources and your network
$threads = 10
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $threads)
$RunspacePool.Open()
$runspace = foreach($ou in $ous) {
$params['SearchBase'] = $ou
$params['Server'] = $dcs[$i++ % $dcs.Count]
$ps = [powershell]::Create()
$ps.AddScript($scriptblock).AddParameter('params', $params)
$ps.RunspacePool = $RunspacePool
[pscustomobject]@{
Instance = $ps
Task = $ps.BeginInvoke()
}
}
# capture the output from each runspace here!
$result = foreach($r in $runspace) {
$r.Instance.EndInvoke($r.Task)
$r.Instance.foreach('Dispose')
}
}
catch {
Write-Warning $_.Exception.Message
}
finally {
$runspace.foreach('Clear')
$RunspacePool.foreach('Dispose')
}
$result | Format-Table
PowerShell 问题给各位精明的人。是否可以根据组大小过滤 Get-ADGroup
命令(也就是仅 return 组大于 x 成员)?我正在尝试以比以下更有效的方式进行过滤:
Get-ADGroup -Filter *
然后 运行 成员计数检查,如 | where {$_.members.count -gt 10,000}
或其他内容。
但是我很难对 初始过滤器 进行任何类型的成员计数检查,所以我不必 return 中的每个组对象个人域,然后检查成员数。这是因为我正在查询的 AD 实例有大量的 AD 组,需要很长时间才能先拉出所有组,然后再检查。
我已经尝试了下面的变体,但我猜测最初的“成员”属性 不存在于您可以查询的属性集中:
Get-ADGroup -Properties members -Filter {members -ge 10,000}
感谢任何帮助!
Is it possible to filter a Get-ADGroup command based on group size (aka only return groups greater than x members)?
没有!
Active Directory 支持的 LDAP 查询过滤器语法没有任何工具来指定 multi-valued 个属性的数量。
您需要在目录中查询具有 any 个成员的组,然后统计结果集 client-side:
Get-ADGroup -LDAPFilter '(&(objectClass=group)(member=*))' -Properties member |Where-Object {
$_.member.Count -gt 10000
}
这就是使用multi-threading提高查询速度的方法,在本例中使用Runspaces,主要思想是获取域中的所有OU,让每个运行空间查询同时一个特定的 OU(与 $threads
中定义的查询一样多)。
这应该可以大大提高脚本的速度,但是,这需要调整,如果同时有太多线程 运行很可能会失败。
$ErrorActionPreference = 'Stop'
# define the params that will be passed to the runspaces
$params = @{
LDAPFilter = "(member=*)"
SearchScope = 'OneLevel'
Properties = 'member'
}
# define the logic of the runspace
$scriptblock = {
param($params)
foreach($group in Get-ADGroup @params) {
if($group.Member.Count -gt 10000) {
$group
}
}
}
try {
# get all OUs
$ous = (Get-ADOrganizationalUnit -Filter *).DistinguishedName
# get all Domain Controllers available
# we don't want to make too many queries to the same DC!!
$dcs = (Get-ADDomainController -Filter *).Name
# define the number of threads that can run at the same time
# maybe you could use `$dcs.Count` as Threads
# this depends on your server's resources and your network
$threads = 10
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $threads)
$RunspacePool.Open()
$runspace = foreach($ou in $ous) {
$params['SearchBase'] = $ou
$params['Server'] = $dcs[$i++ % $dcs.Count]
$ps = [powershell]::Create()
$ps.AddScript($scriptblock).AddParameter('params', $params)
$ps.RunspacePool = $RunspacePool
[pscustomobject]@{
Instance = $ps
Task = $ps.BeginInvoke()
}
}
# capture the output from each runspace here!
$result = foreach($r in $runspace) {
$r.Instance.EndInvoke($r.Task)
$r.Instance.foreach('Dispose')
}
}
catch {
Write-Warning $_.Exception.Message
}
finally {
$runspace.foreach('Clear')
$RunspacePool.foreach('Dispose')
}
$result | Format-Table