Jus*_*Guy 16 powershell filtering active-directory powershell-3.0
我想检查系统中是否已存在用户帐户.
$SamAc = Read-Host 'What is your username?'
$User = Get-ADUser -Filter {sAMAccountName -eq "$SamAc"}
Run Code Online (Sandbox Code Playgroud)
我不确定为什么,但$User即使{sAMAccountName -eq "$SamAc"}应该是真的,也总会返回null .
我在这里错过了什么?
编辑:
这是缺少的:
$User = Get-ADUser -Filter "sAMAccountName -eq '$SamAc'"
Run Code Online (Sandbox Code Playgroud)
编者按:该脚本块({ ... })用替换字符串.
mkl*_*nt0 35
现有答案中有宝贵的信息,但我认为更有针对性的总结是有帮助的:
TL;博士
切勿使用脚本块 - { ... }-构建-Filter-parameter的说法,对于任何 cmdlet的.
Get-Help about_ActiveDirectory_Filter).总是使用字符串来构造-Filter参数参数,因为参数的实际类型是 [string]
Get-ADUser -Filter "sAMAccountName -eq '$SamAc'"Get-Help about_ActiveDirectory_Filter任何参数传递给-Filter被强制转换为字符串第一无论如何,之前它被传递到Get-ADUsercmdlet的,因为-Filter参数的类型为[string]-跨所有支持该参数的cmdlet; 验证Get-ADUser -?
随着-Filter在一般情况下,它是由该cmdlet的解释该字符串,使用特定领域的语言,往往有什么共同之处使用PowerShell.
Get-ADUser,记录了特定于域的语言(查询语言) Get-Help about_ActiveDirectory_Filter使用PowerShell的 字符串插值(从文字和变量引用/表达式或字符串连接),以"烤"的任何变量引用到字符串,在前面.
例如,以下命令全部工作且在功能上等效,使用各种PowerShell技术构造字符串,引用样式和转义字符的变化:
# All these commands are equivalent.
Get-ADUser -Filter "sAMAccountName -eq ""$SamAc"""
Get-ADUser -Filter "sAMAccountName -eq `"$SamAc`"" #`
Get-ADUser -Filter "sAMAccountName -eq '$SamAc'"
Get-ADUser -Filter ('sAMAccountName -eq "' + $SamAc + '"')
Run Code Online (Sandbox Code Playgroud)
重要的是确保通过双引号字符串或显式字符串连接()来$SamAc预先扩展(由其值替换)."..."+ $SamAc + ...
例如,如果$SamAc包含jdoe上述命令,则将以下(等效)文字之一传递给-Filter:
sAMAccountName -eq "jdoe"
sAMAccountName -eq 'jdoe'
Run Code Online (Sandbox Code Playgroud)
但是,对于数字和字符串以外的数据类型,您可能仍需要使用AD提供程序的变量评估(请参阅下文):
例如,AD提供者[1]不会将字符串化[datetime]值(例如08/15/2018 12:45:58)识别为日期.
在那种情况下:
'...')$date),而不是表达式($date.Year或$($date.Year)); 例如:# Note the use of '...' and be sure to use just a variable reference,
# not an expression.
# With this approach, never use embedded quoting, even with string variables.
Get-ADUser -Filter 'whenChanged -ge $date'
Run Code Online (Sandbox Code Playgroud)
警告:此方法不适用于隐式远程处理模块,因为然后在远程计算机上评估变量引用.
转换为字符串时,脚本块会生成和之间的文字内容- 不会发生变量扩展(插值):{}
PS> {sAMAccountName -eq "$SamAc"}.ToString()
sAMAccountName -eq "$SamAc" # !! $SamAc was *not* expanded
Run Code Online (Sandbox Code Playgroud)
因此,它是传递给的文字 .sAMAccountName -eq "$SamAc"Get-ADUser
Get-ADUser,也许是为了支持脚本块语法/更像PowerShell,支持引用变量不带引号 - 注意缺少"around$SamAc:
{ sAMAccountName -eq $SamAc } # as stated, Get-ADUser doesn't see the { and }
Run Code Online (Sandbox Code Playgroud)
也就是说,Get-ADUser它对字符串文字有类似 Powershell的解释:就像你不必在PowerShell表达式中包含变量引用一样(例如),你也不必在这里 - 实际上一定不能,正如OP的尝试失败所证明的那样. sAMAccountName -eq $SamAc"..."'Windows_NT' -eq $env:OS
但是,这种常规PowerShell脚本块的模拟不仅令人困惑 - 因为用户仍然认为他们需要封闭引号 - 但也是半生不熟的,因此很脆弱:
它不适用于属性引用或方法调用:
{ sAMAccountName -eq $searchObj.SamAccountName } # !! DOES NOT WORK
Run Code Online (Sandbox Code Playgroud)它不适用于隐式远程处理模块,因为在远程计算机上评估变量引用,在那里查找变量.
而:
Get-Help about_ActiveDirectory_Filter值得称赞的只是讨论字符串,
它是Get-Help Get-ADUser,令人遗憾的是,使用脚本块所有的例子.
除了一个例外,这些示例仅使用脚本块中的文字,问题永远不会出现.那个例外(截至本文撰写时)是:
-filter { lastLogon -le $logonDate }
Run Code Online (Sandbox Code Playgroud)
这个例子恰好起作用 - 它使用一个没有引号的简单变量引用 - 但是,由于选择了非字符串值,在这种情况下没有人会错误地应用封闭引号- 与比较字符串字段时不同.
脚本块语法诱人且方便,因为引用变得更容易:您不需要嵌套引用.
但是,由于所讨论的所有原因,应该避免.
[1]所述的串-膨胀-的前期的等效可变评价按AD-提供商语句
Get-ADUser -Filter 'whenChanged -ge $date'
是
Get-ADUser -Filter "whenChanged -ge '$date'"
这意味着AD提供商最终看到像
whenChanged -ge '01/15/2018 16:00:00'
作为过滤器表达式; 为了实现这一点,它必须(a)接受一个字符串作为操作数,并且(b)理解PowerShell的日期/时间格式,这是不变文化的格式(类似于美国的日期,首先列出月份,但是24 - 小时).
虽然我无法亲自测试这种行为,但Luke报告称AD提供商确实无法识别此格式.
Jos*_*orn 11
当我第一次开始使用ActiveDirectory模块时,这就是我的一点点,这很难理解.
-FilterActiveDirectory模块cmdlet 的参数实际上是在查找字符串.当你做{sAMAccountName -eq "$SamAc"}这个值时,它实际上是在寻找"sAMAccountName -eq ""`$SamAc"""
基本上,Powershell解析参数并将其值转换为字符串,并且不会插入变量.尝试先建立字符串,它应该工作.
像这样的东西:
$SamAc = Read-Host 'What is your username?'
$filter = "sAmAccountname -eq ""$SamAc"""
$User = Get-ADUser -Filter $filter
Run Code Online (Sandbox Code Playgroud)