Get-Aduser -Filter will not accept a variable

前端 未结 7 788
挽巷
挽巷 2020-11-22 02:09

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 -         


        
相关标签:
7条回答
  • 2020-11-22 02:28
    if (($ADUser = Get-ADUser -filter "SamAccountName -eq '$(Read-Host Username)'") -ne $null) {$ADUser.SamAccountName} else {"Not Found"}
    
    0 讨论(0)
  • 2020-11-22 02:32

    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.

    0 讨论(0)
  • 2020-11-22 02:33

    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

    etc does work as expected

    0 讨论(0)
  • 2020-11-22 02:35

    I have to comment on this because it really aggravated me to sort this out.

    Joseph Alcorn has the right idea. The filter parameter takes a string and then evaluates that in order to process the 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.

    $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. 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.

    0 讨论(0)
  • 2020-11-22 02:41

    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, which 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 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 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.

    0 讨论(0)
  • 2020-11-22 02:42

    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.

    0 讨论(0)
提交回复
热议问题