Using comparison operators on parameters of Powershell cmdlets - powershell

I'm trying to use the Get-BrokerDesktop cmdlet,
Like any other Powershell cmdlets I can pass it parameters to filter out the results to my needs. So, I could do something like,
Get-brokerdesktop -RegistrationState Unregistered
Which would return an object that only has Unregistered as its RegistrationState.
How would I go about having the ones that are not Unregistered?
I tried,
Get-brokerdesktop -RegistrationState -ne Unregistered
Which is invalid syntax.

Actually, I just noticed an example at the bottom of the linked documentation...
The trick here is to use -Filter like so,
Get-BrokerDesktop -Filter { RegistrationState -ne 'Unregistered' }
Or even better in this case, as proposed by #TheIncorrigible1,
-Filter 'RegistrationState -ne "Unregistered"'

Related

Powershell - Use "Set-UnifiedGroup" to change more Groups

)
I wanna set hundred of Groups unvisible in the GAL. Is there a option to do this easy and fast? I am beginner in PowerShell ;) so keep care
Code is:
Set-UnifiedGroup -Identity "GroupName" -HiddenFromAddressListsEnabled $true
It is way to much to do this with all groups. Does anybody know another way?
Thank you so much!
You can iterate through all groups. First you need to get all groups. You can pass the return values to another Cmdlet with a pipe |.
There is a foreach-object loop. This means it will do something for every object returned by Get-UnifiedGroup or any other Cmdlet that returns objects
It should be something like that:
Get-UnifiedGroup | Foreach-Object {
Set-UnifiedGroup -Identity $_.Name -HiddenFromAddressListsEnabled $true
}
As I'm not able to test this be sure the property is $_.Name.
If you just use Get-UnifiedGroup you can see the properties name in the headline

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.

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.

How to use a wildcard in powershell parameter that doesn't natively support it?

Okay, sorry for the probably noobish question.
I've been studying PowerShell for a while now, and have run into something I can't quite figure out how to word correctly for google.
In the most basic sense, here is what I'm trying to do.
Get-Process -id 76*
Now I understand that -id will not handle wildcard * characters.
If I wanted to in theory use
Get-Process -id
and create a wildcard script for this purpose, how would I do this? Do i need to create my own function?
I'd like to add as well that PS says specifically the * is not a usable character for the -Name Parameter, yet I can use this. Is this an error with MS?
Thank you for any advice in advance!
Use a (Where-Object) filter over the Get-Process output.
In this case:
Get-Process | where { $_.Id -like '76*' }
(where is an alias for Where-Object cmdlet.)

Powershell variable without automatic double quotes

Searched but can't find an answer to this (though there are very similar threads).
I have a variable $var = 'string','string2,'string3'
There is a cmdlet I'd like to pass this $var to
Set-DistributionGroup -ManagedBy $var
However, it ends up looking like this:
Set-DistributionGroup -ManagedBy "'string','string2','string3'"
And, I want:
Set-DistributionGroup -ManagedBy 'string','string2','string3'
Is this possible? I wonder if it is, and likely is, a limitation with the Exchange PowerShell cmdlet Set-DistributionGroup. ManagedBy is a MultiValuedProperty per docs.
The basic logic of passing a array of "users" to the -ManagedBy parameter works without any special intervention required. The only thing I can question is the line in you post
Set-DistributionGroup -param $var
Was that an attempt at generalizing the parameter switch name? Makes for some odd output regardless
[PS] >$list = "jim","tim"
[PS] >Set-DistributionGroup -param $list
A positional parameter cannot be found that accepts argument 'jim tim'.
You should have just been able to do this:
[PS] >$list = "jim","tim"
[PS] >Set-DistributionGroup -ManagedBy $list
Assuming that jim and tim resolve to mailboxes. If they were aliases for example.