如何在Active Directory cmdlet上有效使用`-Filter`参数?

时间:2018-07-06 23:19:34

标签: powershell active-directory

我经常在此站点上看到以下针对AD cmdlet的代码类型:

Get-ADUser -Filter * | Where-Object { $_.EmailAddress -eq $email }

问题是您要返回Active Directory中的每个单个用户对象,然后进行第二次处理。我们如何改善这一点,不仅可以减少运行脚本所需的时间,还可以减轻Active Directory以及网络的不必要负担?

1 个答案:

答案 0 :(得分:8)

-Filter *有什么不好的地方?

您正在根据所使用的cmdlet有效地选择并返回AD中存在的每个对象(例如Get-ADUserGet-ADComputerGet-ADGroup,通用Get-ADObject等)-这是一件昂贵的事情,尤其是在较大的AD环境中。如果您合法地需要对每个可能的对象进行操作,则可以这样做,但是在大多数情况下,您不需要返回所有内容。最重要的是,您的脚本最终将处理超出所需数量的数据,从而在不需要时增加了执行时间和使用的处理时间。

-Filter参数所要做的不仅仅是匹配所有内容,实际上是-Filter *所做的。 Filter字符串与Powershell语法非常相似(虽然不尽相同,但大多数方式都如此)。您可以使用Powershell支持的大多数相同的逻辑运算符,并且它们的工作方式与Powershell运算符相同。该答案旨在澄清这一点,并说明如何使用此难以捉摸的参数。这些示例将使用Get-ADUser cmdlet,但这也扩展到了也使用过滤器的其他Get-ADObject cmdlet。

语法

Filter字符串的语法如下:"PropertyName -comparisonoperator 'somevalue'",尽管您可以将多个条件与逻辑运算符(例如-and-or)一起字符串化。请注意,像-match-notmatch这样的正则表达式匹配运算符不起作用,但是-like-notlike可以正常工作。

匹配属性

要使用问题中的示例,我们找到一个与电子邮件地址匹配的用户,但没有管道到Where-Object(疯狂的权利?):

$email = 'box@domain.tld'
Get-ADUser -Filter "EmailAddress -eq '${email}'"

完成。 Get-ADUser将返回任何电子邮件地址属性等于$email变量的帐户。

如果我们要查找过去30天未登录的所有用户帐户怎么办?但是日期字符串比电子邮件更复杂!谁在乎,还是很简单的!

# Get the date from 30 days ago
$notUsedSince = ( Get-Date ).AddDays( -30 )
Get-ADUser -Filter "LastLogonDate -lt '${notUsedSince}'"

这将返回最近30天内未登录的所有用户。

匹配多个属性

匹配多个属性没有太大区别,但是最好将每个条件括在括号()中。下面是一个示例,让我们查找没有与之关联的电子邮件地址的非域管理员帐户(假设我们通过用户名命名*-da知道了这一点)。

Get-ADUser -Filter "(samaccountname -notlike '*-da') -and (EmailAddress -notlike '*')"

这有点棘手,因为我们不能像-Filter那样在EmailAddress中传递条件右侧的空值。但是'*'会匹配任何非空值,因此我们可以利用-notlike比较运算符来利用该行为为EmailAddress查找空值。要细分过滤器,请确保过滤器不匹配任何以-da结尾的帐户,然后还仅匹配不具有EmailAddress值的帐户

要避免的事情

  1. Don't try to use a { ScriptBlock } for your filter parameters。是的,与担心构建ScriptBlock并确保其正确转义相比,我们都更愿意编写string。绝对有使用它们的吸引力。我已经看到很多使用ScriptBlock作为-Filter参数的答案,或者有问题的人(包括我自己)尝试做这样的事情,并且惊讶!什么都不会退回:

    Import-Csv C:\userInfoWithEmails.csv | Foreach-Object { Get-ADUser -Filter { EmailAddress -eq $_.Email } }

    -Filter不支持ScriptBlocks,但它们有时会工作的种类,因为它们在评估之前就已获得ToString。如果您使用$_$emailAddress之类的简单变量扩展,它们在技术上会起作用,但最终会令您头疼,特别是如果您尝试访问对象属性(如上),因为它根本不会工作。每次都使用字符串过滤器,如果需要将对象属性用作过滤器参数,请使用Variable SubstitutionCommand Substitution

  2. 如果您只关心要过滤的属性,则无需指定其他-Properties。 AD cmdlet可以评估Filter参数内的所有属性,而无需将它们传递到管道中。

  3. 当我在使用它时,请勿使用-Properties *,除非您出于某种原因正在检查返回对象的所有属性。仅指定返回AD对象后需要处理的属性。这是有原因的-要获得其值,某些属性特别昂贵。最佳实践是仅转发处理管道所需的属性。与此问题无关,但仍要记住一个非常重要的细节。

总结

-Filter参数与AD cmdlet结合使用的这些技术将在大型AD环境上进行迭代时为您节省昂贵的处理时间,并应改善Powershell AD操作的性能。我希望这有助于解释AD cmdlet的-Filter参数的某些难以捉摸的行为。