user18349
user18349

Reputation: 21

Passing string in Get-ADUser filter parameter causes error - property not found in pscustomobject

I'm trying to create a new Active Directory user, but first I verify that the user doesn't exist already with Get-ADUser. I import the user data from our HR department and build custom properties:

$newUsers = Import-Csv $csvFile |
            Select-Object -Property @{n='EmpNum';e={$_.'Employee Number'}},
                @{n='UPN';e={$_.'Email Address'}},
                @{n='Alias';e={$_.'Email Address'.Split("@")[0]}} #### etc

When I loop through the objects from the CSV file, I use the UPN property to search for the user in Active Directory:

foreach ($newUser in $newUsers) {
    $exists = Get-ADUser -Filter {UserPrincipalName -eq $newUser.UPN} -Properties * -Server $adServer -Credential $adCred 
    ...
}

The filter causes an error:

Get-ADUser : Property: 'UPN' not found in object of type:
'System.Management.Automation.PSCustomObject'. At
C:\Users\bphillips.NEWHOPEOFIN\Dropbox\Powershell\NewHire\AddNewDSP.ps1:50
char:15
+     $exists = Get-ADUser -Filter {UserPrincipalName -eq $newUser.UPN} -Propertie ...

I've tried doing this: -Filter {UserPrincipalName -eq $("$newUser.UPN") but that doesn't help; I get another error

Get-ADUser : Cannot process argument because the value of argument
"path" is not valid. Change the value of the "path" argument and run
the operation again. At
C:\Users\bphillips.NEWHOPEOFIN\Dropbox\Powershell\NewHire\AddNewDSP.ps1:50
char:15
+     $exists = Get-ADUser -Filter {UserPrincipalName -eq $("$newUser.UPN")} -Prop ...

$newUser is a string, so I don't understand why it causes a problem. Hard-coding a UserPrincipalName like, "[email protected]" works, but the $newUser.UPN won't work.**

PS C:\> $newUser.UPN.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

and

PS C:\> $newUser.UPN | gm

   TypeName: System.String

$newUser.UPN contains a valid string value

PS C:\> $newUser.UPN
[email protected]

What do I have to do to get $newUser.UPN to be recognized as a string for the filter parameter? What's going on that I don't understand?

Upvotes: 2

Views: 13682

Answers (3)

mklement0
mklement0

Reputation: 437933

  • Never use a script block ({ ... }) as the -Filter argument - the -Filter parameter's type is [string] - construct your filter as a string.

  • While seemingly convenient, using a script block only works in very limited scenarios and causes confusion when it doesn't work - such as when involving property access, as in this case.

For more information, see this answer of mine.

Upvotes: 0

BenH
BenH

Reputation: 10044

Expressions can inside the filter block of a Get-ADUser but they need to be properly wrapped with quotes.

Get-ADUser -Filter "UserPrincipalName -eq '$($newUser.UPN)'"

Upvotes: 1

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200293

The BNF for filter query strings does not allow expressions as the second operand in a comparison, only values (emphasis mine):

Syntax:
The following syntax uses Backus-Naur form to show how to use the PowerShell Expression Language for this parameter.

<filter> ::= "{" <FilterComponentList> "}"
<FilterComponentList> ::= <FilterComponent> | <FilterComponent> <JoinOperator> <FilterComponent> | <NotOperator> <FilterComponent>
<FilterComponent> ::= <attr> <FilterOperator> <value> | "(" <FilterComponent> ")"
<FilterOperator> ::= "-eq" | "-le" | "-ge" | "-ne" | "-lt" | "-gt"| "-approx" | "-bor" | "-band" | "-recursivematch" | "-like" | "-notlike"
<JoinOperator> ::= "-and" | "-or"
<NotOperator> ::= "-not"
<attr> ::= <PropertyName> | <LDAPDisplayName of the attribute>
<value>::= <compare this value with an <attr> by using the specified <FilterOperator>>

Put the value of the property you want to compare against in a variable and use that variable in the comparison. You may also want to define the filter as an actual string, if only for clarity (despite what it looks like the filter is not a scriptblock).

$upn = $newUser.UPN
$exists = Get-ADUser -Filter "UserPrincipalName -eq '$upn'" ...

Upvotes: 3

Related Questions