Using variables in EMS Filter parameter
The Filter parameter is one of my favorite parameters in EMS (Exchange Management Shell). It is one of the most robust parameters in EMS as it enables us to filter objects on the server (using a PowerShell expression) instead of using the Where-Object cmdlet, which filters objects on the client.
In Exchange 2007, we could use a simple filter expression to get all mailbox objects which have the Office attribute set to 'Sales':
[PS] > Get-Mailbox -Filter {Office -eq 'Sales'} | Format-Table Name,Office -AutoSize
Name Office
---- ------
User1 Sales
User2 Sales
User3 Sales
...
We could also use a variable to hold the value and use the variable in the filter:
[PS] $Office = ‘Sales’
[PS] > Get-Mailbox -Filter {Office -eq $Office} | Format-Table Name,Office -AutoSize
Name Office
---- ------
User1 Sales
User2 Sales
User3 Sales
...
Now let’s try the same command (using the variable assignment) in EMS 2010:
[PS] $Office = ‘Sales’
[PS] > Get-Mailbox -Filter {Office -eq $Office} | Format-Table Name,Office -AutoSize
Name Office
---- ------
DiscoverySearchMailbox {D919BA05-46A6-415f-80AD-7E09334BB852}
Shay Levy
As you can see the results are not the same, instead we get all mailbox objects that do not have a value in the Office property, as if the value of $Office is $null. Adding the Verbose switch parameter to the command reveals that the value does not evaluated properly (thanks Michael):
[PS] > Get-Mailbox -Filter {Office -eq $Office} –Verbose
VERBOSE: [18:29:10.013 GMT] Get-Mailbox : Searching objects of type "ADUser" with filter
"(&((|((RecipientTypeDetails Equal RoomMailbox)(RecipientTypeDetails Equal EquipmentMailbox)
(RecipientTypeDetails Equal LegacyMailbox)(RecipientTypeDetails Equal LinkedMailbox)
(RecipientTypeDetails Equal UserMailbox)(RecipientTypeDetails Equal DiscoveryMailbox)
(RecipientTypeDetails Equal SharedMailbox)))(!((Exists(Office))))))", scope "SubTree" under the
root "$null".
It seems that the variable is passed to the EMS remote session without expanding it's value first. That gave me an idea, what if use double quotes instead of braces to force the variable to expand?
[PS] > Get-Mailbox -Filter "Office -eq $Office"
Invoke-Command : Cannot bind parameter 'Filter' to the target. Exception setting "Filter":
"Invalid filter syntax. For a description of the filter parameter syntax see the command help.
"office -eq sales" at position 12."
Now we get an error that the filter is invalid but look at the error, the variable was expanded, it is invalid because the string we are comparing against is not wrapped in quotes. Since we used double quotes to enable variable substitution lets try to wrap the variable in single quotes:
[PS] > Get-Mailbox -Filter "Office -eq '$Office'" | Format-Table Name,Office -AutoSize
Name Office
---- ------
User1 Sales
User2 Sales
User3 Sales
User4 Sales
...
And it works! PowerShell expands the variable locally before it passes on to the remote EMS session.