如何在Active Directory cmdlet上有效使用`-Filter`参数? [英] How to effectively use the `-Filter` parameter on Active Directory cmdlets?

查看:98
本文介绍了如何在Active Directory cmdlet上有效使用`-Filter`参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

All too often I see the following type of code on this site, specific to the AD cmdlets:

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

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

The problem is that you are returning every single user object in Active Directory, and then processing it a second time. How can we improve upon this, not only to reduce the time it takes to run the script, but to also take the unnecessary load off of Active Directory, and possibly the network?

推荐答案

-过滤器* 有什么不好?



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

What is so bad about -Filter *?

You are effectively selecting and returning every object that exists in AD, based on the cmdlet you are using (e.g. Get-ADUser, Get-ADComputer, Get-ADGroup, the generic Get-ADObject, etc.) - this is an expensive thing to do, especially in larger AD environments. It is fine to do this if you legitimately need to operate on every possible object, but in most cases you do not need to return everything. On top of this, your script will end up processing far more data than it needs to, increasing execution time and used processing time when it just isn't necessary.

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

The -Filter parameter can do more than just match on everything, which is effectively what -Filter * does. The Filter string is very much like Powershell syntax (not quite, but most of the way there). You can use most of the same logical operators that Powershell supports, and they work much in the same way that Powershell operators do. This answer aims to clarify this and explain how to use this elusive parameter. These examples will use the Get-ADUser cmdlets but this also extends to the other Get-ADObject cmdlets which use filters as well.

Filter 字符串如下: PropertyName -comparisonoperator'somevalue' ,尽管您可以将多个条件与逻辑运算符(例如-和-或。请注意,正则表达式匹配运算符(例如 -match -notmatch )不起作用,但- code>和不一样就像您期望的那样。

The syntax for the Filter string is as follows: "PropertyName -comparisonoperator 'somevalue'", though you can string multiple conditions together with logical operators such as -and and -or. Note that regex matching operators, like -match and -notmatch do not work, but -like and -notlike work as you would expect.

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

To use the example in the question, let's find a user matching an email address, but without piping to Where-Object (crazy right???):

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

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

Done. Get-ADUser will return any accounts where the EmailAddress property equals whatever the $email variable is.

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

What if we want to find all user accounts that haven't been logged onto in the last 30 days? But a date string is more complex than an email! Who cares, still pretty simple!

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

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

This returns all users who have not logged on in the last 30 days.

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

Matching on multiple properties is not much different, but it's best to wrap each condition in parentheses (). Here's an example, let's find non-domain admin accounts (assuming we know this by the username nomenclature *-da) that don't have an email address associated with them.

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

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

This one is a little trickier, because we can't pass in an empty value for the right side of a condition in the -Filter, as in the case for EmailAddress. But '*' matches any non-empty value, so we can leverage that behavior with the -notlike comparison operator to find empty values for EmailAddress. To break down the filter, make sure that any accounts ending in -da aren't matched by the filter, and then also only match accounts that do not have an EmailAddress value.


  1. 不要尝试使用 {ScriptBlock} 作为过滤器参数。是的,与担心构建字符串并确保其正确转义相比,我们更愿意编写 ScriptBlock 。绝对有使用它们的吸引力。我已经看到很多使用 ScriptBlock 作为 -Filter 参数的答案,或者遇到问题的人(包括我自己)试图做这样的事情,惊喜!什么都不会返回:

  1. Don't try to use a { ScriptBlock } for your filter parameters. Yes, we are all more comfortable with writing a ScriptBlock than worrying about building a string and making sure it's escaped properly. There is definitely an attraction to using them. I've seen so many answers using a ScriptBlock as a -Filter argument, or people having problems (myself included) trying to do something like this, and SURPRISE!!! Nothing gets returned:

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

-过滤器不支持 ScriptBlocks ,但它们 Kind of Work Betweenever™ ,因为它们可以在评估之前,使用ToString。如果您使用简单的变量扩展(例如 $ _ $ emailAddress ),它们在技术上会起作用,但最终会导致您令人头疼的是,特别是如果您尝试访问对象属性(如上),因为它根本无法工作。每次都使用字符串过滤器,如果需要将对象属性用作过滤器参数,请使用变量替换命令替换

-Filter doesn't support ScriptBlocks, but they Kind of Work Sometimes™ because they get ToString'd before getting evaluated. They will technically work if you use simple variable expansion like $_ or $emailAddress, but it will eventually cause you a headache, especially if you try to access an object property (like above) because it simply won't work. Use a string filter every time, and if you need to use an object property as a filter parameter, use Variable Substitution or Command Substitution.

您无需指定其他属性(如果您只在乎要过滤的属性)。 AD cmdlet可以评估 Filter 参数内的所有属性,而无需将其传递到管道中。

You do not need to specify additional -Properties if you only care about a property to filter on it. The AD cmdlets can evaluate all properties within the Filter parameter without needing to pass them down the pipeline.

在我使用它时,请勿使用 -Properties * ,除非您出于某种原因正在检查返回对象的所有属性。仅指定返回AD对象后需要处理的属性。这是有原因的-要获得其值,某些属性特别昂贵。最佳实践是仅转发处理管道所需的属性。

And while I'm at it, don't ever use -Properties *, excepting maybe if you are inspecting all properties on a returned object for some reason. Only specify the properties you need to process after the AD object has been returned. There is a reason for this - some properties are particularly expensive to get the values for. Best practice is to only forward the properties you need to process down the pipeline. A little unrelated to this question but still a very important detail to keep in mind.



总结



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

In summarium

These techniques using the -Filter parameter with the AD cmdlets will save you costly processing time when iterating over large AD environments, and should improve the performance of your Powershell AD operations. I hope this helps explain some of the elusive behaviors of the AD cmdlets' -Filter parameter.

这篇关于如何在Active Directory cmdlet上有效使用`-Filter`参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆