Powershell 如何在Active Directory cmdlet上有效地使用“-Filter”参数?
我经常在此网站上看到以下特定于AD cmdlet的代码类型:Powershell 如何在Active Directory cmdlet上有效地使用“-Filter”参数?,powershell,active-directory,Powershell,Active Directory,我经常在此网站上看到以下特定于AD cmdlet的代码类型: Get-ADUser -Filter * | Where-Object { $_.EmailAddress -eq $email } 问题是您正在返回Active Directory中的每个用户对象,然后再次处理它。我们如何改进这一点,不仅要减少运行脚本所需的时间,还要减少不必要的Active Directory负载,可能还有网络负载 关于Azure AD cmdlet的注意事项 此答案是围绕已安装的Active Directory
Get-ADUser -Filter * | Where-Object { $_.EmailAddress -eq $email }
问题是您正在返回Active Directory中的每个用户对象,然后再次处理它。我们如何改进这一点,不仅要减少运行脚本所需的时间,还要减少不必要的Active Directory负载,可能还有网络负载
关于Azure AD cmdlet的注意事项
此答案是围绕已安装的Active Directory cmdlet精心编制的,可从远程服务器管理工具(RSAT)
获得。但是,Azure AD cmdlet使用(OData v4.0规范)对Azure AD运行查询,而[1]则依赖于PowerShell表达式引擎的实现来替换LDAP筛选器
因此,如果不进行一些修改以与Microsoft Graph规范(特别是its)兼容,下面的筛选器示例将无法与Azure AD cmdlet一起使用。但是,此处提到的一般做法仍应适用
[1] -这是我能找到的本文件的最新版本
-Filter*
有什么不好的地方?
根据您使用的cmdlet(例如,Get-ADUser
,Get-ADComputer
,Get-ADGroup
,Get-ADGroup
,通用的Get-ADObject
,等等),您可以有效地选择并返回AD中存在的每个对象-这是一件昂贵的事情,尤其是在较大的AD环境中。如果您合法地需要对每个可能的对象进行操作,那么这样做是可以的,但在大多数情况下,您不需要返回所有对象。除此之外,您的脚本最终将处理远远超出其需要的数据,从而增加执行时间,并在不需要时使用处理时间
-Filter
参数可以做的不仅仅是匹配所有内容,这正是-Filter*
所做的。-Filter
字符串与Powershell语法非常相似(不完全相同,但大部分情况下都是如此)。您可以使用Powershell支持的大多数逻辑运算符,它们的工作方式与Powershell运算符的工作方式基本相同。这个答案旨在阐明这一点,并解释如何使用这个难以捉摸的参数。这些示例将使用Get-ADUser
cmdlet,但这也扩展到了其他Get-ADObject
cmdlet,它们也使用过滤器
语法
-Filter
字符串的语法如下:“PropertyName-comparisonoperator'somevalue'”
,但您可以使用逻辑运算符(如-和和-或)将多个条件串在一起。请注意,正则表达式匹配运算符,如-match
和-notmatch
不起作用,但-like
和-notlike
的作用与您预期的一样
属性上的匹配
要使用问题中的示例,让我们找到一个与电子邮件地址匹配的用户,但没有管道连接到Where Object
(对吗?)
完成了Get ADUser
将返回EmailAddress属性等于$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
比较运算符利用该行为来查找电子邮件地址的空值。要分解筛选器,请确保筛选器未匹配以-da
结尾的任何帐户,然后仅匹配没有电子邮件地址值的帐户
避免的事情
。是的,编写脚本块
比构建字符串
并确保其正确转义更容易。使用它们肯定有吸引力。我已经看到很多答案使用ScriptBlock
作为-Filter
参数,或者有问题的人(包括我自己)试图做这样的事情,并且很惊讶!!!不返回任何内容:
Import-Csv C:\userInfoWithEmails.csv | Foreach-Object {
Get-ADUser -Filter { EmailAddress -eq $_.Email }
}
-Filter
不支持脚本块
,但有时它们支持类工作™因为他们在接受评估之前就开始尝试了。如果您使用简单的变量扩展,如$\uuu
或$emailAddress
,它们在技术上是有效的,但最终会让您头疼,特别是如果您试图访问对象属性(如上文所述),因为它根本不起作用。每次使用字符串筛选器,如果需要将对象属性用作筛选器参数,请使用或
如果只关心要在其上进行筛选的属性,则无需指定其他-Properties
。AD cmdlet可以计算-Filter
参数中的所有属性,而无需将它们传递到管道中
当我这样做时,永远不要使用-Properties*
,除非您出于某种原因检查返回对象上的所有属性,例如在脚本开发期间,或者以交互方式不太确定要查找什么(请注意)。
只指定需要处理的属性
Import-Csv C:\userInfoWithEmails.csv | Foreach-Object {
Get-ADUser -Filter { EmailAddress -eq $_.Email }
}