Get-Aduser -Filter 不接受变量 [英] Get-Aduser -Filter will not accept a variable

查看:23
本文介绍了Get-Aduser -Filter 不接受变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

$SamAc = Read-Host '你的用户名是什么?'$User = Get-ADUser -Filter {sAMAccountName -eq "$SamAc"}

我不知道为什么,但是即使 {sAMAccountName -eq "$SamAc"} 应该是 true,$User 也会总是返回 null.>

我在这里遗漏了什么?

这是缺少的:

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

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

解决方案

现有答案中有有价值的信息,但我认为更有针对性的总结会有所帮助.请注意,此答案的原始形式提倡严格避免 脚本块 ({...}) 和 AD-provider 变量评估,但是这已被更细微的建议所取代.

tl;dr

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 },技术上也有效,但在概念上有问题 - 见底部.

警告:如果您通过 隐式远程处理模块 - 是否通过 Import-PSSession 或者,在 PowerShell v7+ 中,通过 Windows 兼容性功能 - 都没有 '...'{ ... } 都有效,因为变量引用会在远程机器上进行评估,在那里寻找变量(徒劳无功);如果 (Get-Command Get-ADUser).CommandType 返回 Function,则您使用的是隐式远程处理模块.

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

背景

  • 您传递给 -Filter 的任何参数都被强制转换为 string 第一之前传递给 Get-ADUser cmdlet,因为 -Filter 参数的类型是 [string] - 就像 all 一样 支持此参数的提供程序 cmdlet;使用 Get-ADUser -?

    验证
  • 通常使用 -Filter,这取决于 cmdlet(底层的 PowerShell provider) 来解释该字符串,使用域特定(查询)语言通常与 PowerShell 几乎没有共同之处.

    • 对于 Get-ADUser,该域特定语言(查询语言)记录在 获取关于_ActiveDirectory_Filter的帮助.

      • 注意:在撰写本文时,此遗留主题的更新版本不存在;这个 GitHub 问题请求一个.
    • 使用 Get-AdUser,这种语言当然建模在 PowerShell 上,但它有许多限制和一些必须注意的行为差异,特别是:

      • 仅支持有限的 PowerShell 操作符子集,有些操作符表现出不同的行为;这是一个非详尽列表:

        • -like/-notlike 仅支持通配符表达式中的 *(不支持 ? 和字符集/范围 ([...])
          • '*' 本身代表任何 非空 值(与 PowerShell 的通配符表达式不同,它也匹配空值).* 使用 -notlike '*' 代替 -eq ""-eq $null 来测试字段是否为空.
          • 某些 AD 字段,例如 DistinguishedName支持 '*' 本身,不作为一部分更大的图案;也就是说,它们只支持空性测试.
        • 不支持正则表达式匹配.
        • -lt/-le-gt/-ge 只执行词法em> 比较.
        • 引用不存在/拼写错误的属性名称会导致 Get-ADUser 命令悄悄返回 $null.
        • 无法使用 -eq $true 测试 Enabled 属性 - 请参阅 这个答案.
      • 如前所述,仅支持简单变量引用(例如,$SamAc),还支持表达式(例如,$SamAc.Name$("admin_" + $SamAc))

  • 虽然您可以使用脚本块 ({ ... }) 将变成字符串的内容传递给 -Filter,虽然这种语法对于嵌入引号方便,但它有两个问题:

    • 它可能会误导您认为您正在传递一段PowerShell 代码;值得注意的是,您可能倾向于使用不受支持的运算符和表达式,而不是简单的变量引用.

    • 它会产生不必要的工作(尽管这在实践中不太可能发生),因为您强制 PowerShell 首先将过滤器解析为 PowerShell 代码,只有在参数为绑定到 -Filter.

I'd like to check if a user account already exists in the system.

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

I'm not sure why, but $User will always return null even if {sAMAccountName -eq "$SamAc"} is supposed to be true.

What am I missing here?

Edit:

This is what was missing:

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

Editor's note: The script block ({ ... }) was replaced with a string.

解决方案

There is valuable information in the existing answers, but I think a more focused summary is helpful. Note that the original form of this answer advocated strict avoidance of script blocks ({...}) and AD-provider variable evaluation, but this has been replaced with more nuanced recommendations.

tl;dr

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

  • Do not quote the variable reference ("$SamAc").

  • Only use simple variable references (e.g, $SamAc); expressions are not supported (e.g., $SamAc.Name or $("admin_" + $SamAc)); if necessary, use an intermediate, auxiliary variable; e.g.:

    • $name = "admin_" + $SamAc; Get-ADUser -Filter 'sAMAccountName -eq $name'
  • Generally, only a subset of PowerShell's operators are supported, and even those that are do not always behave the same way - see bottom section.

  • Use '...' to quote the -Filter argument as a whole.

    • While use of a script block ({ ... }),
      Get-ADUser -Filter { sAMAccountName -eq $SamAc }, technically works too, it is conceptually problematic - see bottom section.

Caveat: If you use Get-ADUser via an implicitly remoting module - whether self-created via Import-PSSession or, in PowerShell v7+, via the Windows Compatibility feature - neither '...' nor { ... } works, because the variable references are then evaluated on the remote machine, looking for the variables there (in vain); if (Get-Command Get-ADUser).CommandType returns Function, you're using an implicitly remoting module.

  • In that event you must use PowerShell's string interpolation ("...") or string concatenation from literals and variable references / expressions in order to "bake" any variable / expression values into the string, up front:
    Get-ADUser -Filter "sAMAccountName -eq `"$SamAc`""
  • Note that for string operands embedded quoting then is necessary.
  • Also, be sure to `-escape constants such as $true, $false, and $null inside the "..." string, so that PowerShell doesn't expand them up front.
  • Caveat: This technique may not work with all data types; at least the default stringification of a [datetime] instance (e.g., 01/15/2018 16:00:00 is not recognized by the AD provider; in this case, embedding the result of a call to the instance's .ToFileTime() method into the string may help (untested); I'm unclear on whether there are other data types that require similar workarounds.

Background

  • Any argument you pass to -Filter is coerced to a string first, before it is passed to the Get-ADUser cmdlet, because the -Filter parameter is of type [string] - as it is for all provider cmdlets that support this parameter; verify with Get-ADUser -?

  • With -Filter in general, it is up to the cmdlet (the underlying PowerShell provider) to interpret that string, using a domain-specific (query) language that often has little in common with PowerShell.

    • In the case of Get-ADUser, that domain-specific language (query language) is documented in Get-Help about_ActiveDirectory_Filter.

      • Note: As of this writing, no newer version of this legacy topic exists; this GitHub issue requests one.
    • With Get-AdUser, this language is certainly modeled on PowerShell, but it has many limitations and some behavioral differences that one must be aware of, notably:

      • Only a limited subset of PowerShell operators are supported, and some exhibit different behavior; here's a non-exhaustive list:

        • -like / -notlike only support * in wildcard expressions (not also ? and character sets/ranges ([...])
          • '*' by itself represents any nonempty value (unlike in PowerShell's wildcard expressions, where it also matches an empty one). * Instead of -eq "" or -eq $null to test fields for being empty, use -notlike '*'.
          • Certain AD fields, e.g., DistinguishedName, only support '*' by itself, not as part of a larger pattern; that is, they only support an emptiness test.
        • There is no support for regex matching.
        • -lt / -le and -gt / -ge only perform lexical comparison.
        • Referencing a nonexistent / misspelled property name causes the Get-ADUser command to quietly return $null.
        • The Enabled property cannot be tested for with -eq $true - see this answer.
      • As stated, only simple variable references are supported (e.g, $SamAc), not also expressions (e.g., $SamAc.Name or $("admin_" + $SamAc))

  • While you can use a script block ({ ... }) to pass what becomes a string to -Filter, and while this syntax can be convenient for embedding quotes, it is problematic for two reasons:

    • It may mislead you to think that you're passing a piece of PowerShell code; notably, you may be tempted to use unsupported operators and expressions rather than simple variable references.

    • It creates unnecessary work (though that is unlikely to matter in practice), because you're forcing PowerShell to parse the filter as PowerShell code first, only to have the result converted back to a string when the argument is bound to -Filter.

这篇关于Get-Aduser -Filter 不接受变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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