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

问题描述

我正在开发一种工具,该工具可以快速运行 csv 并在 AD 中搜索提供的相关信息 我制作了一个 gui,可以让用户将 CSV 的标题与 AD 搜索方法对齐

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

及其在选择条目上的错误 限制在任一时间运行的 powershell 作业的数量似乎有助于解决此问题 但并没有完全消除它

这是我目前正在使用的

$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,EmailAddress

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

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

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

当然,您需要熟悉 LDAP 搜索过滤器语法并查看 AD 中的原始 LDAP 属性值才能有效地使用它,但对于它提供的性能提升而言,这是一个很小的代价。

,

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

虽然我很难引用参考文献,但我知道 -Filter 参数在客户端上由 AD cmdlet 解释/转换为 LDAP 查询-side,然后作为 LDAP 查询字符串转发到服务器。

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

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

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

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

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

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