关于powershell:Get-Aduser -Filter将不接受变量

Get-Aduser -Filter will not accept a variable

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

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

我不确定为什么,但是即使{sAMAccountName -eq"$SamAc"}应该为true,$User仍将始终返回null。

我在这里想念什么?

编辑:

这是缺少的内容:

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

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


现有答案中包含有价值的信息,但是我认为更集中的摘要会有所帮助。请注意,此答案的原始形式提倡严格避免使用脚本块和AD提供程序变量评估,这些建议已被更细微的建议所取代。

好的。

tl; dr

好的。

1
Get-ADUser -Filter 'sAMAccountName -eq $SamAc'

  • 不要引用变量引用( "$SamAc" )。

    好的。

  • 仅使用简单的变量引用(例如,$SamAc);不支持表达式(例如$SamAc.Name$("admin_" + $SamAc));如有必要,请使用中间辅助变量;例如。:

    好的。

  • $name ="admin_" + $SamAc; Get-ADUser -Filter 'sAMAccountName -eq $name'
  • 好的。

  • 通常,仅支持一部分PowerShell操作符,即使那些操作符也不总是以相同的方式运行-请参阅底部。

    好的。

  • 使用'...'引用整个-Filter参数。

    好的。

  • 使用脚本块({ ... })时,
    Get-ADUser -Filter { sAMAccountName -eq $SamAc }从技术上讲也可行,从概念上讲是有问题的-请参阅底部。
  • 好的。

    好的。

    注意:如果通过隐式远程处理模块使用Get-ADUser-无论是通过Import-PSSession自行创建,还是在PowerShell v7 +中通过Windows兼容性功能自行创建-'...'{ ... }均不起作用,因为这样会引用变量在远程机器上求值,寻找那里的变量(徒劳);如果(Get-Command Get-ADUser).CommandType返回Function,则说明您使用的是隐式远程处理模块。

    好的。

  • 在那种情况下,您必须使用PowerShell的字符串内插("...")或从文字和变量引用/表达式的字符串连接,以将任何变量/表达式值"烘焙"到字符串中,预先:
    Get-ADUser -Filter"sAMAccountName -eq `"$SamAc`""
  • 请注意,对于字符串操作数,则必须使用嵌入式引号。
  • 另外,请确保在"..."字符串内使用` -escape常量(例如$true$false$null),以便PowerShell不会在前面扩展它们。
  • 注意:这项技术可能不适用于所有数据类型。至少[datetime]实例的默认字符串化(例如,AD提供程序无法识别01/15/2018 16:00:00;在这种情况下,将对实例的.ToFileTime()方法的调用结果嵌入到字符串中可能会有所帮助(未经测试) ;我不清楚是否还有其他数据类型需要类似的解决方法。
  • 好的。


    背景

  • 传递给-Filter的任何参数在传递给Get-ADUser cmdlet之前,都将被强制转换为字符串,因为-Filter参数的类型为[string]-就像支持该参数的所有cmdlet一样。用Get-ADUser -?验证

    好的。

  • 通常,使用-Filter时,由cmdlet(底层PowerShell提供程序)使用特定于域的(查询)语言来解释该字符串,而该语言通常与PowerShell很少相同。

    好的。

  • 对于Get-ADUser,该特定于域的语言(查询语言)以Get-Help about_ActiveDirectory_Filter记录。

    好的。

  • 注意:在撰写本文时,此旧主题的更新版本不存在。这个GitHub问题要求一个。
  • 好的。

  • 使用Get-AdUser时,该语言无疑是在PowerShell上建模的,但是它具有许多局限性和一些行为差异,您必须意识到,尤其是:

    好的。

  • 仅支持PowerShell运算符的有限子集,其中一些表现出不同的行为;这是一个非详尽的清单:

    好的。

  • -like / -notlike仅在通配符表达式中支持*(还不支持?和字符集/范围([...]))

  • '*'本身表示任何非空值(与PowerShell的通配符表达式不同,该值也匹配一个空值)。
    *使用-notlike '*'代替-eq""-eq $null来测试字段是否为空。
  • 某些AD字段(例如DistinguishedName)仅单独支持'*',而不能作为较大模式的一部分;也就是说,它们仅支持空度测试。
  • 好的。

  • 不支持正则表达式匹配。
  • -lt / -le-gt / -ge仅执行词汇比较。
  • 引用不存在的/拼写错误的属性名称会使Get-AdUser命令悄悄地返回$null
  • Enabled属性无法使用-eq $true进行测试-请参见此答案。
  • 好的。

  • 如上所述,仅支持简单的变量引用(例如$SamAc),不支持表达式(例如$SamAc.Name$("admin_" + $SamAc))

    好的。

  • 好的。

    好的。

  • 尽管您可以使用脚本块({ ... })将变成字符串的内容传递给-Filter,并且此语法可以方便地嵌入引号,但由于两个原因,这是有问题的:

    好的。

  • 可能会误导您以为您正在传递一段PowerShell代码。值得注意的是,您可能很想使用不受支持的运算符和表达式,而不是简单的变量引用。

    好的。

  • 它创建了不必要的工作(尽管在实践中不太重要),因为您正在强制PowerShell首先将过滤器作为PowerShell代码解析为过滤器,仅在将参数绑定到-Filter时才将结果转换回字符串。

    好的。

  • 好的。

    好的。

    好。


    当我第一次开始使用ActiveDirectory模块时,这一点让我很吃力,而弄清楚这一点却很痛苦。

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

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

    像这样:

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


    我必须对此发表评论,因为它确实使我无法解决这个问题。

    约瑟夫·奥尔康(Joseph Alcorn)有一个正确的想法。 filter参数采用字符串,然后对其进行求值以处理过滤器。令人们感到困扰的是,您可以选择使用大括号而不是{},如果您使用Where ...,这将无法正常工作,它仍然必须像字符串一样对待。

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

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


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


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

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

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

    这应该很好。


    好的,我终于可以使用以下语法并从上方开始使用以下示例进行工作:

    先前:

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

    工作版本:

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

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