电源壳 |在 Powershell 作业中加速 运行 Get-ADUser

Powershell | Speed up Running Get-ADUser in Powershell jobs

我正在开发一种工具,可以通过 csv 快速 运行 并在 AD 中搜索所提供的相关信息 我制作了一个图形用户界面,可以让用户将 CSV 的 header 与 AD 搜索方法

对齐

我目前的主要问题是在 AD 中搜索 EmailAddress 变量时,我经常遇到错误 “与用于处理请求的目录的连接不可用。这可能是暂时的情况。”

及其在 select 条目上的错误 在任何时候限制 powershell 作业的数量 运行ning 似乎有助于解决这个问题 但并没有完全消除它

这是我目前正在使用的东西

$maxConcurrentJobs=15
$CheckBlock = {
            param ($User)
            Try { Get-ADUser -Filter { EmailAddress -eq $User } -Properties SamAccountName, EmployeeID, EmailAddress }
            Catch { Return "$User - $_" }
        }
        $Array.($listbox_Columns.SelectedItem) | ForEach-Object{
            $Check = $false 
            while ($Check -eq $false)
            {
                if ((Get-Job -State 'Running').Count -lt $maxConcurrentJobs)
                {
                    Write-Host "Processing EmailAddress $_"
                    Start-Job -ScriptBlock $CheckBlock -ArgumentList $_
                    $Check = $true
                }
            }
        }

我建议搬到 -LDAPFilter,像这样:

Get-ADUser -LDAPFilter "(mail=$User)" -Properties SamAccountName, EmployeeID, EmailAddress

并以此为基础,最佳方式是一次性搜索所有用户。这也可以用 -LDAPFilter 完成,但需要做更多的工作。

$mails = $listbox_Columns.SelectedItem  # this should be an array of email addresses
$filter = $mails -join ')(mail='

Get-ADUser -LDAPFilter "(|(mail=$filter))" -Properties SamAccountName, EmployeeID, EmailAddress

此时您很有可能不再需要将其分配给许多作业,这已经非常高效了。

第二个代码示例中发生了什么:

$mails -join ')(mail='(|(mail=$filter)) 一起以 (|(mail=A)(mail=B)(mail=C)) 等形式创建一个 LDAP 搜索表达式,这将为您提供所有匹配的对象(但没有别的)服务器往返。

当然,您需要熟悉 LDAP 搜索过滤器语法并查看 AD 中的原始 LDAP 属性 值才能有效地使用它,但这是为它提供的性能提升。

很抱歉,这不适合发表评论,但我一直在观看这个讨论,目的是插话。

虽然我很难引用参考文献,但我知道 -Filter 参数是 interpreted/translated 通过 AD[=43 进入 LDAP 查询=] cmdlet,在客户端,然后作为 LDAP 查询字符串转发到服务器。

这可以通过在 DC 上执行 -Filter 查询以查看记录的内容来提高 NTDS 日志记录来证明,我敢打赌它将是转换后的 LDAP 查询。此外,这是有道理的,因为 AFAIK AD LDAP(非接口)无法回答任何其他类型的查询。我打算使用这种方法仔细检查是我延迟参与的原因。

多年来,我反复测试了 -Filter-LDAPFilter 之间的性能,并反复得出在任一方向摆动的极小差异。鉴于一般的性能可变性,我的结论是几乎没有区别!虽然我们可以假设 -Filter 参数的解释涉及一些开销,但它可能最小到无法检测到的程度。包括在该开销中的是查询计算属性(如“已启用”)的能力。 Get-ADUser 返回的 属性 可能是 UserAccountControl 的按位解释,但是可以使用 -Filter 查询它。关于那个和其他 properties/attributes 存在一些争论,但我可以亲自证明它的可靠性并在其他 SO 讨论中提到过它。

注意:对于更复杂的查询,这些结果可能会有所不同。但是,增加的复杂性可能会导致人们出于其他更直接的原因使用 -LDAPQuery

我目前找不到这些讨论,但我会尝试更新此注释。我知道我得出了类似的结论并评论了@mklement0 的一个答案,他将我带到了@tomolak 的一个答案,我在其中记录了类似的评论。

我也早就认识到,针对广泛需求的广泛单一查询比重新运行多次 Get-* 快得多。在某种程度上,这似乎是普遍的,而不是特定于 AD cmdlet。如果我需要检查用户是否存在数千次,首先加载所有用户的列表,然后检查列表比 运行 Get-ADUser 快得多。当然,如果我只需要检查几个用户,公式可能会转向另一个方向。这种坚定的观察可能是代码加速的原因,-Filter-LDAPFilter.

之间没有任何区别

根据我的经验,-LDAPFilter 的真正用例是当某些属性无法使用 -Filter 查询时。这可能是由于给定 属性 缺少 Filter > LDAPFilter 转换。所以,我能给出的最好的建议是使用 -Filter 直到你不能,然后在需要时切换到 -LDAPFilter。我不能排除其他用例,也许是不同 AD cmdlet 之间查询字符串的可移植性?尽管如此,如果您对 LDAP 查询一般或具体感到满意,那么使用它们肯定不会造成功能上的损害。