简体   繁体   English

Get-Aduser -Filter 将不接受变量

[英]Get-Aduser -Filter will not accept a variable

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.我不知道为什么,但$User将始终返回 null 即使{sAMAccountName -eq "$SamAc"}应该是真的。

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 .编者注:脚本块( {... } ) 被替换为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.请注意,此答案的原始形式提倡严格避免脚本块( {...} ) 和AD-provider 变量评估,但这已被更细微的建议所取代。

tl;dr tl;博士

Get-ADUser -Filter 'sAMAccountName -eq $SamAc'
  • Do not quote the variable reference (不要引用变量引用( "$SamAc" ). )。

  • Only use simple variable references (eg, $SamAc );只使用简单的变量引用(例如, $SamAc ); expressions are not supported (eg, $SamAc.Name or $("admin_" + $SamAc) );支持表达式(例如, $SamAc.Name$("admin_" + $SamAc) ); if necessary, use an intermediate, auxiliary variable;如有必要,使用中间辅助变量; eg:例如:

    • $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.通常,仅支持 PowerShell 运算符的一个子集,甚至那些不总是以相同方式运行的运算符 - 请参阅底部部分。

  • Use '...' to quote the -Filter argument as a whole.使用'...'-Filter参数作为一个整体引用。

    • While use of a script block ( { ... } ),在使用脚本块 ( { ... } ) 时,
      Get-ADUser -Filter { sAMAccountName -eq $SamAc } , technically works too, it is conceptually problematic - see bottom section. Get-ADUser -Filter { sAMAccountName -eq $SamAc } ,技术上也有效,但在概念上有问题 - 请参阅底部部分。

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);注意事项:如果您使用Get-ADUser通过 隐式远程处理模块-无论是通过自我创造Import-PSSession或在PowerShell中V7 +,通过Windows兼容性功能-既没有'...' ,也不{ ... }的工作,因为然后在远程机器上评估变量引用,在那里寻找变量(徒劳); if (Get-Command Get-ADUser).CommandType returns Function , you're using an implicitly remoting module.如果(Get-Command Get-ADUser).CommandType返回Function ,则您使用的是隐式远程处理模块。

  • 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 :在这种情况下,你必须使用PowerShell的字符串插值"..." )或从文字和变量引用/表达式字符串连接,以‘硬’的任何变量/表达式到字符串前面
    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.此外,请确保在"..."字符串中使用` -escape 常量,例如$true$false$null ,以便 PowerShell 不会预先扩展它们。
  • Caveat : This technique may not work with all data types;警告:此技术可能不适用于所有数据类型; at least the default stringification of a [datetime] instance (eg, 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.至少是[datetime]实例的默认字符串化(例如,AD 提供程序无法识别01/15/2018 16:00:00 ;在这种情况下,嵌入对实例的.ToFileTime()方法的调用结果进入字符串可能有帮助(未经测试);我不清楚是否还有其他数据类型需要类似的解决方法。

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;传递给Get-ADUser cmdlet之前您传递给-Filter任何参数首先被强制转换为字符串,因为-Filter参数的类型为[string] - 与支持此参数的所有提供程序 cmdlet 一样; verify with Get-ADUser -?使用Get-ADUser -?验证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 .使用-Filter通常,由cmdlet (底层PowerShell 提供程序)来解释该字符串,使用通常与 PowerShell 几乎没有共同点域特定(查询)语言

    • In the case of Get-ADUser , that domain-specific language (query language) is documented in Get-Help about_ActiveDirectory_Filter .Get-ADUser的情况下,该域特定语言(查询语言)记录在Get-Help about_ActiveDirectory_Filter

      • Note: As of this writing, no newer version of this legacy topic exists;注意:在撰写本文时,不存在此遗留主题的更新版本; this GitHub issue requests one. 这个 GitHub 问题需要一个。
    • 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:有了Get-AdUser ,这种语言当然是仿照PowerShell建模的,但它有许多限制和一些必须注意的行为差异,特别是:

      • Only a limited subset of PowerShell operators are supported, and some exhibit different behavior;仅支持有限的 PowerShell 操作符子集,有些操作符表现出不同的行为; here's a non-exhaustive list:这是一个非详尽列表:

        • -like / -notlike only support * in wildcard expressions (not also ? and character sets/ranges ( [...] ) -like / -notlike只支持*在通配符表达式(不还?和字符集/范围( [...]
          • '*' by itself represents any nonempty value (unlike in PowerShell's wildcard expressions, where it also matches an empty one). '*'本身代表任何非空值(与 PowerShell 的通配符表达式不同,它也匹配空值)。 * Instead of -eq "" or -eq $null to test fields for being empty, use -notlike '*' . * 使用-notlike '*'代替-eq ""-eq $null来测试字段是否为空。
          • Certain AD fields, eg, DistinguishedName , only support '*' by itself , not as part of a larger pattern;某些 AD 字段,例如DistinguishedName支持'*'本身,而不是作为更大模式的一部分; that is, they only support an emptiness test.也就是说,它们只支持空性测试。
        • There is no support for regex matching.不支持正则表达式匹配。
        • -lt / -le and -gt / -ge only perform lexical comparison. -lt / -le-gt / -ge仅执行词法比较。
        • Referencing a nonexistent / misspelled property name causes the Get-ADUser command to quietly return $null .引用不存在/拼写错误的属性名称会导致Get-ADUser命令安静地返回$null
        • The Enabled property cannot be tested for with -eq $true - see this answer .无法使用-eq $true测试Enabled属性 - 请参阅此答案
      • As stated, only simple variable references are supported (eg, $SamAc ), not also expressions (eg, $SamAc.Name or $("admin_" + $SamAc) )如前所述,只支持简单的变量引用(例如, $SamAc ),不支持表达式(例如, $SamAc.Name$("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:虽然您可以使用脚本块 ( { ... } ) 将变成字符串的内容传递给-Filter ,并且这种语法对于嵌入引号方便,但由于两个原因而存在问题:

    • It may mislead you to think that you're passing a piece of PowerShell code;它可能会误导您认为您正在传递一段PowerShell代码; 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 .它会产生不必要的工作(尽管这在实践中不太可能发生),因为您强制 PowerShell 首先将过滤器解析为 PowerShell 代码,只有在参数绑定到-Filter时才将结果转换回字符串。

This one bit me when I first started to work with the ActiveDirectory module, and it was a pain to figure out.当我第一次开始使用 ActiveDirectory 模块时,这一点让我很头疼,想弄清楚这件事很痛苦。

The -Filter parameter for the ActiveDirectory module cmdlets is actually looking for a string. ActiveDirectory 模块 cmdlet 的-Filter参数实际上是在寻找一个字符串。 When you do {sAMAccountName -eq "$SamAc"} as the value, it is actually looking for "sAMAccountName -eq ""`$SamAc"""当你做{sAMAccountName -eq "$SamAc"}作为值时,它实际上是在寻找"sAMAccountName -eq ""`$SamAc"""

Basically, Powershell parses the parameter and turns its value into a string, and will not interpolate the variable.基本上,Powershell 解析参数并将其值转换为字符串,并且不会插入变量。 Try building the string before hand, and it should work.尝试事先构建字符串,它应该可以工作。

Something like this:像这样的东西:

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

I have to comment on this because it really aggravated me to sort this out.我必须对此发表评论,因为解决这个问题真的让我很恼火。

Joseph Alcorn has the right idea. Joseph Alcorn 的想法是正确的。 The filter parameter takes a string and then evaluates that in order to process the filter. filter 参数采用一个字符串,然后对其进行评估以处理过滤器。 What trips people up with this is that you are given the option to use curly brackets instead {}, and this doesn't work as you'd expect if you were using Where... it still has to be treated like a string.使人们对此感到困惑的是,您可以选择使用大括号代替 {},如果您使用 Where,这将不会像您期望的那样工作......它仍然必须被视为一个字符串。

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

I recommend sticking to quotes to make it more clear/readable for yourself and others and to avoid potential syntax errors, or stick to Where{} in the pipeline.我建议坚持使用引号,以使其对自己和他人更清晰/易读,并避免潜在的语法错误,或者坚持使用管道中的 Where{}。 When doing so, I find it best to use double-quotes on the outside & single-quotes on the inside so you still get intellisense detection on the variable.这样做时,我发现最好在外部使用双引号并在内部使用单引号,这样您仍然可以对变量进行智能检测。

Simply remove the quotes around your variable:只需删除变量周围的引号:

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

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

This should work just fine.这应该工作得很好。

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

It took me quite a bit to just use我花了很多时间才使用

Do not quote the variable reference ("$SamAc").不要引用变量引用 ("$SamAc")。

TXH so much TXH这么多

Okay, I got mine to finally work using the following syntax and using the following example from up above:好的,我终于使用以下语法并使用上面的以下示例来完成工作:

Previously:以前:

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

Working Version:工作版本:

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

I had to add $($ ) to $SamAc before PowerShell could access the variable string value.在 PowerShell 可以访问变量字符串值之前,我必须将 $($ ) 添加到 $SamAc。

Little addendum if anyone like me got here and was still tearing their hair out:如果像我这样的人来到这里并且仍在撕扯他们的头发,请补充一点:

-properties *  

Would be quite a common this to have in this query.在此查询中将是很常见的。 Doesn't work, I'm sure someone smarter than me can figure it out没用,我相信有人比我聪明能弄明白

-properties mail,cn,wtf -properties mail,cn,wtf

etc does work as expected等确实按预期工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM