Get-Aduser -Filter不接受变量

时间:2013-11-19 15:27:42

标签: powershell active-directory filtering powershell-v3.0

我想检查系统中是否已存在用户帐户。

$SamAc = Read-Host 'What is your username?'
$User = Get-ADUser -Filter {sAMAccountName -eq "$SamAc"}

我不确定原因,但$User将始终返回null,即使{sAMAccountName -eq "$SamAc"}应该为真。

我在这里缺少什么?

编辑:

这是缺少的:

$User = Get-ADUser -Filter "sAMAccountName -eq '$SamAc'"

编者注: 脚本块{ ... })已替换为字符串。功能

7 个答案:

答案 0 :(得分:33)

现有答案中有宝贵的信息,但我认为更有针对性的总结是有帮助的:

<强> TL;博士

  • 绝不使用脚本块 - { ... } - 来构建-Filter - 参数参数 for 任何 cmdlet

    • 仅在非常有限的情况下才有效 - 见下文。
    • 错误地认为过滤器是一段 PowerShell 代码,它不是(Active Directory提供商只支持少数,PowerShell- 喜欢运算符,但它们的行为部分与PowerShell对应的行为不同 - 请参阅Get-Help about_ActiveDirectory_Filter)。
  • 始终使用字符串 构建-Filter - 参数参数,因为参数的实际类型是< / em> [string]

正确而强大的方法是构建字符串

  • 您传递给-Filter的任何参数无论如何都会被强制转换为字符串之前将传递给Get-ADUser cmdlet ,因为-Filter参数的类型为[string] - 跨支持此参数的所有 cmdlet;使用Get-ADUser -?

  • 进行验证
  • 通常使用-Filter cmdlet 可以使用特定于域的语言来解释该字符串,该语言通常具有< em>与PowerShell 没什么共同之处。

使用 PowerShell 字符串插值(或文字和变量引用/表达式的字符串连接)到&#34; bake&#34;任何变量都将引用到字符串预先

例如,以下命令全部工作且在功能上等效,使用各种 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 + '"')

重要的一点是确保$SamAc通过双引号字符串"..."或显式字符串连接来预先扩展(由其值替换) (+ $SamAc + ...)。

例如,如果$SamAc包含jdoe,则上述命令会将以下(等效)文字之一传递给-Filter

sAMAccountName -eq "jdoe"
sAMAccountName -eq 'jdoe'

但是,如果数据类型不是数字和字符串,您可能仍需要使用 AD提供商的变量评估 (见下文):

例如,AD提供商 [1] 不会将字符串化的[datetime]值(例如08/15/2018 12:45:58)识别为日期。

在那种情况下:

  • 使用单个引用的字符串('...'
  • 请务必仅使用简单变量引用(例如$date),而不是表达式$date.Year$($date.Year)) ; e.g:
# 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' 

警告:此方法无法使用implicitly remoting modules,因为然后在远程计算机上评估变量引用。

如果您指定脚本块 - 您应该避免

脚本块在转换为字符串时,会在{} - no 变量扩展(插值)之间生成文字内容)发生:

 PS> {sAMAccountName -eq "$SamAc"}.ToString()
 sAMAccountName -eq "$SamAc"  # !! $SamAc was *not* expanded

因此,传递给sAMAccountName -eq "$SamAc"文字 Get-ADUser

Get-ADUser或许以支持脚本块语法/更像PowerShell,支持支持引用变量< em>未加引号 - 请注意" 周围缺少$SamAc

{ sAMAccountName -eq $SamAc }  # as stated, Get-ADUser doesn't see the { and }

Get-ADUser对字符串 literal sAMAccountName -eq $SamAc执行自己的Powershell- 之类的解释:就像你没有做过一样必须将"..."中的变量引用括在PowerShell表达式中(例如'Windows_NT' -eq $env:OS),您不必在此处 - 并且实际上必须不是,正如OP尝试失败所证明的那样。

但是,常规PowerShell脚本块的仿真不仅令人困惑 - 因为用户仍然认为他们需要附上引号 - 但半成品< / strong>,因此脆弱

  • 它不能与属性引用方法调用一起使用:

    { sAMAccountName -eq $searchObj.SamAccountName } # !! DOES NOT WORK
    
  • 它不能与implicitly remoting modules一起使用,因为在远程计算机上评估变量引用,在那里查找变量

脚本块混淆的来源

while:

除了一个例外,示例在脚本块中仅使用 literals ,问题永远不会出现。 一个例外(截至本文撰写时)是:

-filter { lastLogon -le $logonDate }

这个例子恰好起作用 - 它使用了一个没有引号的简单变量引用 - 但是,由于选择了非字符串值,没有人会试图在中错误地应用封闭引号 case - 与比较 string 字段时不同。

脚本块语法诱人且方便,因为引用变得更容易:您不需要嵌套引用。
但是,由于所讨论的所有原因,应该避免使用。

[1]字符串扩展前端等效的AD-provider变量评估语句
Get-ADUser -Filter 'whenChanged -ge $date'
Get-ADUser -Filter "whenChanged -ge '$date'"
这意味着AD提供商最终会看到类似的东西 whenChanged -ge '01/15/2018 16:00:00'
作为过滤表达式;要使其工作,必须(a)接受字符串作为操作数,并且(b)了解PowerShell的日期/时间格式,即invariant culture& #39; s格式(类似美国的日期,首先列出月份,但是24小时制) 虽然我无法亲自测试此行为,但Luke报告AD提供商确实识别此格式。

答案 1 :(得分:11)

当我第一次开始使用ActiveDirectory模块时,这就是我的一点,而且很难理解。

ActiveDirectory模块cmdlet的-Filter参数实际上是在查找字符串。当您{sAMAccountName -eq "$SamAc"}作为值时,它实际上正在寻找"sAMAccountName -eq ""`$SamAc"""

基本上,Powershell会解析参数并将其值转换为字符串,并且不会插入变量。尝试先建立字符串,它应该可以工作。

这样的事情:

$SamAc = Read-Host 'What is your username?'    
$filter = "sAmAccountname -eq ""$SamAc"""
$User = Get-ADUser -Filter $filter

答案 2 :(得分:2)

我必须对此发表评论,因为它真的让我很难解决这个问题。

Joseph Alcorn有正确的想法。 filter参数接受一个字符串,然后对其进行求值以处理过滤器。让人们感到高兴的是,你可以选择使用大括号而不是{},如果你使用的是Where,它就不会像你期望的那样......它仍然必须像字符串一样对待。

$SamAc = Read-Host 'What is your username?'
$User = Get-ADUser -Filter "sAMAccountName -eq '$SamAc'"

我建议坚持使用引号使其对自己和他人更清晰/可读,并避免潜在的语法错误,或者坚持使用管道中的Where {}。这样做时,我发现最好在外面使用双引号和&amp;内部使用单引号,因此您仍然可以对变量进行intellisense检测。

答案 3 :(得分:0)

只需删除变量周围的引号:

$SamAc = Read-Host 'What is your username?'

$User = Get-ADUser -Filter {sAMAccountName -eq $SamAc}

这应该可以正常工作。

答案 4 :(得分:0)

if (($ADUser = Get-ADUser -filter "SamAccountName -eq '$(Read-Host Username)'") -ne $null) {$ADUser.SamAccountName} else {"Not Found"}

答案 5 :(得分:0)

如果有像我这样的人来到这里,仍然在扯头发,那是很少的附录:

-properties *  

在查询中会很常见。不起作用,我敢肯定有人比我聪明

-属性mail,cn,wtf

etc确实按预期工作

答案 6 :(得分:-1)

好的,我让我最终使用以下语法并使用上面的示例:

此前:

$User = Get-ADUser -Filter "sAMAccountName -eq '$SamAc'"

工作版:

$user = Get-aduser -Filter "sAMAccountName -eq '$($SamAc)'"

在PowerShell访问变量字符串值之前,我必须在$ SamAc中添加$($)。

希望这对某人有帮助!