Get-Aduser -Filter will not accept a variable - powershell

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.
Option A: Letting the AD provider resolve - stand-alone only - variable references:
Get-ADUser -Filter 'sAMAccountName -eq $SamAc' # note the '...' quoting
Note the use of '...', i.e. a verbatim (single-quoted) string, because the string's value is to be passed as-is to the AD provider (cmdlet).
While use of a script block ({ ... }), Get-ADUser -Filter { sAMAccountName -eq $SamAc }, technically works too (its verbatim content, sans { and }, is converted to a string), it is conceptually problematic - see bottom section.
Do not quote the variable reference ("$SamAc").
Use only stand-alone variable references (e.g, $SamAc); expressions are not supported (e.g., $user.SamAccountName or "$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.
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.
If implicit remoting is involved, you MUST use string interpolation, as shown next.
Option B: Using PowerShell's string interpolation (expandable strings), up front:
Get-ADUser -Filter "sAMAccountName -eq `"$SamAc`"" # note the "..." quoting
Using "...", i.e. an expandable (double-quoted) string makes PowerShell interpolate (expand) all variable references and subexpression up front, in which case the AD provider sees only the (variable-free) result.
As shown above, for string operands embedded quoting then is necessary.
For embedded quoting, '...' is a simpler alternative to `"...`" (`" is an _escaped "), but note that this assumes that an expanded value doesn't itself contain ', which is a distinct possibility with last names, for instance.
Also, be sure to `-escape constants such as $true, $false, and $null inside the "..." string, which are always recognized by the AD provider; i.e., use `$true, `$false and `$null, so that PowerShell doesn't expand them up front.
Caveat: Using an expandable string does not work with all data types, at least not directly: for instance, 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() (or .ToFileTimeUtc()?) method into the string may be necessary (as suggested in the comments on this post); I'm unclear on whether there are other data types that require similar workarounds.
On the plus side, string interpolation allows you to embed entire expressions and even commands in a "..." string, using $(...), the subexpression operator; e.g.:
# Property access.
Get-ADUser -Filter "sAMAccountName -eq `"$($user.SamAccountName)`""
# String concatenation
Get-ADUser -Filter "sAMAccountName -eq `"$('admin_' + $SamAc)`""
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, the language supported by -Filter is certainly modeled on PowerShell, but it has many limitations and some behavioral differences that one must be aware of, notably:
As Santiago Squarzon points out, these limitations and difference stem from the fact that the language is translated into an LDAP filter behind the scenes, it is therefore constrained by its features and behaviors. (Note that you can use the -LDAPFilter parameter in lieu of -Filter to directly pass an LDAP filter).
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.
As stated, only stand-alone 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.

This one bit me when I first started to work with the ActiveDirectory module, and it was a pain to figure out.
The -Filter parameter for the ActiveDirectory module cmdlets is actually looking for a string. When you do {sAMAccountName -eq "$SamAc"} as the value, it is actually looking for "sAMAccountName -eq ""`$SamAc"""
Basically, Powershell parses the parameter and turns its value into a string, and will not interpolate the variable. 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. 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.

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"}

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

It took me quite a bit to just use
Do not quote the variable reference ("$SamAc").
TXH so much

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.

Related

Searching partial names with Powershell [duplicate]

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.
Option A: Letting the AD provider resolve - stand-alone only - variable references:
Get-ADUser -Filter 'sAMAccountName -eq $SamAc' # note the '...' quoting
Note the use of '...', i.e. a verbatim (single-quoted) string, because the string's value is to be passed as-is to the AD provider (cmdlet).
While use of a script block ({ ... }), Get-ADUser -Filter { sAMAccountName -eq $SamAc }, technically works too (its verbatim content, sans { and }, is converted to a string), it is conceptually problematic - see bottom section.
Do not quote the variable reference ("$SamAc").
Use only stand-alone variable references (e.g, $SamAc); expressions are not supported (e.g., $user.SamAccountName or "$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.
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.
If implicit remoting is involved, you MUST use string interpolation, as shown next.
Option B: Using PowerShell's string interpolation (expandable strings), up front:
Get-ADUser -Filter "sAMAccountName -eq `"$SamAc`"" # note the "..." quoting
Using "...", i.e. an expandable (double-quoted) string makes PowerShell interpolate (expand) all variable references and subexpression up front, in which case the AD provider sees only the (variable-free) result.
As shown above, for string operands embedded quoting then is necessary.
For embedded quoting, '...' is a simpler alternative to `"...`" (`" is an _escaped "), but note that this assumes that an expanded value doesn't itself contain ', which is a distinct possibility with last names, for instance.
Also, be sure to `-escape constants such as $true, $false, and $null inside the "..." string, which are always recognized by the AD provider; i.e., use `$true, `$false and `$null, so that PowerShell doesn't expand them up front.
Caveat: Using an expandable string does not work with all data types, at least not directly: for instance, 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() (or .ToFileTimeUtc()?) method into the string may be necessary (as suggested in the comments on this post); I'm unclear on whether there are other data types that require similar workarounds.
On the plus side, string interpolation allows you to embed entire expressions and even commands in a "..." string, using $(...), the subexpression operator; e.g.:
# Property access.
Get-ADUser -Filter "sAMAccountName -eq `"$($user.SamAccountName)`""
# String concatenation
Get-ADUser -Filter "sAMAccountName -eq `"$('admin_' + $SamAc)`""
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, the language supported by -Filter is certainly modeled on PowerShell, but it has many limitations and some behavioral differences that one must be aware of, notably:
As Santiago Squarzon points out, these limitations and difference stem from the fact that the language is translated into an LDAP filter behind the scenes, it is therefore constrained by its features and behaviors. (Note that you can use the -LDAPFilter parameter in lieu of -Filter to directly pass an LDAP filter).
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.
As stated, only stand-alone 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.
This one bit me when I first started to work with the ActiveDirectory module, and it was a pain to figure out.
The -Filter parameter for the ActiveDirectory module cmdlets is actually looking for a string. When you do {sAMAccountName -eq "$SamAc"} as the value, it is actually looking for "sAMAccountName -eq ""`$SamAc"""
Basically, Powershell parses the parameter and turns its value into a string, and will not interpolate the variable. 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. 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.
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"}
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
It took me quite a bit to just use
Do not quote the variable reference ("$SamAc").
TXH so much
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.

using "-Filter" and "-Like" with a variable

I've got a hair pulling problem (I think)
Here's the code:
$dn="abc.com"
Get-Recipient -Filter {EmailAddresses -Like '$dn'} -- didn't work
Get-Recipient -Filter {EmailAddresses -Like '*$dn*'} -- didn't work
Get-Recipient -Filter {EmailAddresses -Like *'$dn'*} -- didn't work
Get-Recipient -Filter {EmailAddresses -Like '*abc.com*'} -- WORKS
How can I make it work with a variable, instead of a literal string value?
Thanks in advance.
Use an expandable string (interpolating string, "..."):
Get-Recipient -Filter "EmailAddresses -Like '*$dn*'"
Note that Get-Recipient's -Filter argument is a string, and that using a script block ({ ... }) is not only unnecessary, but leads to conceptual confusion.
In fact, when a script block is passed, its verbatim content (except { and }) is used as the string value, so no expansion of variable references takes place.
NoteThanks, AdminOfThings: Unlike Get-ADUser (see this answer), Get-Recipient can not perform variable interpretation of its own, so an expandable string ("...") is always needed if PowerShell variables or expressions other than $null, $true and $false are to be used in a filter, which must then be escaped as `$null, `$true and `$false.
Otherwise, use single-quoting (verbatim strings, '...'), where no escaping (other than escaping embedded ' as '') is needed - see Recipient filters in Exchange PowerShell commands and string literals in PowerShell.
A PowerShell variable inside of single quotes is not expanded, so $dn is not abc.com but $dn, just replace the single quotes with double quotes.

Get-AzureADUser filter - "A script block cannot be evaluated without input"

Can somebody explain to me why the following works:
$email = 'fred#bloggs.com'
Get-ADUser -Filter {mail -eq $email}
But when I do this:
$email = "fred#bloggs.com"
Get-AzureADUser -Filter {mail -eq $email}
I get:
Get-AzureADUser : Cannot evaluate parameter 'Filter' because its argument is specified as a script block and there is no input. A script block cannot be evaluated without input.
Thanks.
These two commands use two different types of filters.
Get-ADUser uses PowerShell Expression Language syntax. It can accept surrounding {} even though they technically should not be used because it is not really a scriptblock. This also means that you can use a subset of PowerShell operators like -eq, -like, etc. The proper syntax for this filter is "mail -eq '$email'". The inside quotes are needed because PowerShell will expand the string inside of the double quotes before passing it to Get-ADUser, which will result in mail -eq user#domain.com (notice there are no quotes surrounding the email address) and throw an error.
Get-AzureADUser uses an oData v3.0 filter statement. That specification does not allow for PowerShell operator syntax as it has its own rules. It also does now allow the scriptblock ({}) syntax. The proper way to construct this filter is -Filter "mail eq '$email'". Notice it uses eq rather than -eq. With oData filters, you gain access to functions that can make data retrieval and manipulation easier. An example of using a function is Get-AzureADUser -Filter "startswith(Mail,'$email')".
See Get-ADUser to see more information on the -Filter parameter for Get-ADUser.
See Get-AzureADUser to see more information on the Get-AzureADUser -Filter parameter.
An additional link oData Filter Querying Collections contains a table of acceptable operators and functions to add significant capabilities for querying.

Filter by two properties with Get-ADUser

Get-ADUser -SearchBase "OU=Purgatory,DC=domain,DC=com" -Filter {'enabled -eq $false' -and 'whenChanged -lt $ChangeDate'}
I cant figure out how to filter by two traits. I want to filter by disabled users that are older than the $ChangeDate variable. If I filter just by 'enabled -eq $false', it works, and if I filter just by 'whenChanged -lt $ChangeDate' , it works. But if i use the -and to combine them, no luck.
Generally, you should avoid the use of script blocks ({ ... }) as -Filter arguments.
Ultimately, whatever is passed to the -Filter parameter is a string, and using { ... } only obscures that fact, because it falsely suggests that the enclosed expression is a piece of PowerShell code - it is not; it is a severely constrained, PowerShell-like language described in Get-Help about_ActiveDirectory_Filter
What muddies the waters is that the AD provider happens to recognize simple variable references (e.g., $ChangeDate) in the strings it ultimately receives (and use of { ... } effectively passes ... as a string literal), whereas any expression (e.g., $ChangeDate.Year) is not recognized.
Generally, the safest approach is to use expandable (interpolating) strings (double-quoted; "...") as -Filter arguments and "bake in" variable values; that is, PowerShell replaces the variable references with their values before the AD provider sees the string.
However, it's unclear how date values must be represented inside such a string in order to be recognized as such, so taking advantage of the
variable interpretation offered by the AD provider happens to be the safest choice in this case (note the use of single quotes ('...'), which means that the string is passed as-is - PowerShell performs no interpolation):
Get-ADUser -SearchBase "OU=Purgatory,DC=domain,DC=com" `
-Filter 'enabled -eq $false -and whenChanged -lt $ChangeDate'
Again, be aware that you're passing a string literal to -Filter, and that it is the AD provider interpreting the embedded variable references, which only works with simple variable references, not expressions.
As for what you tried:
{'enabled -eq $false' -and 'whenChanged -lt $ChangeDate'} is effectively passed by calling the .ToString() method on it, which passes everything between the { and } as-is.
That is, the cmdlet / AD provider sees
'enabled -eq $false' -and 'whenChanged -lt $ChangeDate'
as the string value, including the single quotes, which is not what you intended.

Why doesn't $PSItem behave as expected when using a bracket-based -Filter argument?

I was assisting a user with this question, linked to my answer here: Powershell script to add users to A/D group from .csv using email address only?
Initially I wrote the script as follows, using a bracket-based filter for Get-AdUser like follows:
Import-CSV "C:\users\Balbahagw\desktop\test1.csv" |
Foreach-Object {
# Here, $_.EmailAddress refused to resolve
$aduser = Get-ADUser -Filter { EmailAddress -eq $_.EmailAddress }
if( $aduser ) {
Write-Output "Adding user $($aduser.SamAccountName) to groupname"
Add-ADGroupMember -Identity groupname -Members $aduser
} else {
Write-Warning "Could not find user in AD with email address $($_.EmailAddress)"
}
}
However, $_.EmailAddress failed to populate a value. However, changing the Get-ADUser filter to a string-based filter worked as intended:
$aduser = Get-ADUser -Filter "EmailAddress -eq '$($_.EmailAddress)'"
What is the strangeness I'm experiencing, and why? Is it because when I'm using brackets, it's treated as a new scope and the $PSItem won't follow?
-Filter parameters are generally string parameters (verify with
Get-Help Get-AdUser -Parameter Filter)
They generally do not accept PowerShell code - filters are provider-specific and often have their own syntax, although it happens to be PowerShell-like in the case of the AD cmdlets.
Also, they generally have no knowledge of PowerShell variables (see below).
Thus, when a script block ({ ... }) is passed, it is converted to a string, which evaluates to its literal contents (everything between the opening { and the closing }):
{ EmailAddress -eq $_.EmailAddress }.ToString() yields the literal string EmailAddress -eq $_.EmailAddress - without any evaluation - and that's what Get-AdUser sees - no evaluation takes place.
In a presumably well-meaning but misguided effort to support the widespread, but ill-advised practice of passing script blocks to the -Filter parameter of AD cmdlets, it seems that these cmdlets actually explicitly expand simple variable references such as $_ in the string literal they receive, but that doesn't work with expressions, such as accessing a property of a variable ($_.EmailAddress)
Therefore, -Filter arguments should generally be passed as expandable strings ("..."); in the case at hand:
-Filter "EmailAddress -eq '$($_.EmailAddress)'"
That is, the only robust solution is to use strings with the variable parts baked in, up front, via string expansion, as shown above.
For values that are neither numbers nor strings, such as dates, you may have to use a literal string ('...') and rely on the AD provider's ability to evaluate simple references to PowerShell variables (e.g., $date) - see this answer of mine for details.
As stated, the syntax of AD filters is only PowerShell-like: it supports only a subset of the operators that PowerShell supports and those that are supported differ subtly in behavior - see Get-Help about_ActiveDirectory_Filter.
It is tempting to use script blocks, because the code inside requires no escaping of embedded quotes / no alternating of quote chars and no use of subexpression operator $(...). However, aside from using script blocks as strings being inefficient in general, the problem here is that the script block is making a promise that it cannot keep: it looks like you're passing a piece of PowerShell code, but you're not - and it works only in simple cases (and then only due to the misguided accommodation mentioned above); generally, it's hard to remember under what circumstances it doesn't work and how to make it work if it fails.
It is therefore really unfortunate that the official documentation uses script blocks in its examples.
For a more comprehensive discussion, see this answer of mine.
You're not wrong, it's the module's fault
The type of payload you have to use with the -Filter parameter differs depending on which provider you're working with, a design decision which can be pretty confusing!
The output of Get-Help Get-ADUser -Parameter Filter gives you some pretty detailed examples of the different syntax options you can use with the Active Directory Provider's implementation of Filter syntax.
Here's an example:
#To get all user objects that have an e-mail message attribute, use one of the following commands:
Get-ADUser -Filter {EmailAddress -like "*"}
It looks like the ActiveDirectory provider places the specific restriction that you must wrap the input in quotes. Here's what happens when I look for my account without putting quotes around my e-mail.
Get-ADUser -Filter {EmailAddress -eq stephen#foxdeploy.com}
Get-ADUser : Error parsing query: 'EmailAddress -eq stephen#foxdeploy.com'
Error Message: 'syntax error' at position: '18'.
But adding quotes? It works!
Get-ADUser -Filter {EmailAddress -eq "stephen#foxdeploy.com"}
DistinguishedName : CN=Stephen,CN=Users,DC=FoxDeploy,DC=local
Enabled : True
GivenName : Stephen
Name : Stephen
ObjectClass : user
ObjectGUID : 6428ac3f-8d17-45d6-b615-9965acd9675b
SamAccountName : Stephen
SID : S-1-5-21-3818945699-900446794-3716848007-1103
Surname :
UserPrincipalName : Stephen#FoxDeploy.local
How to make yours work
Now, because of this confusing filter implementation, you will need to change your user lookup on line 5 to the following:
$aduser = Get-ADUser -Filter "EmailAddress -eq `"$($_.EmailAddress)`""
We are providing the -Filter payload as a String. Next we want to use String Expansion to pull out the .EmailAddress property, so we wrap the string in $( ) to signal string expansion. Finally, the provider wants our filter comparison wrapped in quotes, so we put double quotes around it, and then escape the quotes using the backtick character.
And now it should work.
TLDR - blame the provider and blame the module, there are so many inconsistencies with the Active Directory module.