Last Update: Sep 04, 2024 | Published: Jun 07, 2016
Over the course of a few articles, I’ve been introducing you to PowerShell operators. Most of them like -eq and -And are not that difficult to figure out if you see them in an example. PowerShell has several other operators that I describe as special use and may not be intuitive, but I think you will find them quite useful.
The range operator (..) is a quick way to get a range of numbers in either ascending or descending order.
This operator only works with integer values.
I like using the range operator as a counter.
1..5 | foreach { "do something here on pass $_" }
This will run the code in the ForEach-Object loop five times.
Or you could use it like this to build a random password.
Function New-Password { Param([int]$Length = 7) -join (33..126 | Get-Random -count $length | foreach {$_ -as [char]} ) }
And maybe you want to generate a list of passwords
The call operator (&) is used to invoke or run an expression. You might have a scriptblock you are using with Invoke-Command, but you will need to test it.
True, I could also have used Invoke-Command to test the scriptblock. But you can also use this operator to invoke commands stored as variables.
But it can’t parse an expression with parameters.
However, because the Call operator is simply invoking the command, you can still pass parameters like this:
The static member operator (::) confuses newcomers. Part of the problem is that this is part of the .NET world. In .NET, sometimes you have to construct an instance of an object before you can invoke or run any of the object’s methods. In those situations you would use the . operator.
$now = Get-Date $then = $now.AddDays(100)
I had to create a [Datetime] object before I could invoke the AddDays() method. But some .NET classes have methods that are considered static. In these situations, you don’t need to create an instance of the object. You can invoke the method directly from the class. The [math] class is a great example.
[math]::pi [math]::Pow(2,3)
Or here is a more practical example:
Get-CimInstance win32_logicaldisk -filter "drivetype = 3" -ComputerName $c | Select DeviceID, @{Name="SizeGB";Expression = {($_.size/1GB) -as [int]}}, @{Name="FreeGB";Expression = { [math]::Round($_.freespace/1gb,4)}}, @{Name="PctFree";Expression = { [math]::Round(($_.freespace/$_.size) *100,2)}}, PSComputername | Out-GridView -Title "Drive Report"
You’ll also notice I’m using a few other operators I’ve discussed in previous articles. Invoking the static methods from the [Math] class produces a much nicer report.
Most of the time you don’t need to define a PowerShell array ahead of time. But you can explicitly create an empty array using @().
Note that this technique will create an array of a fixed size so you can’t necessarily use all methods of an array object.
Notice at the end the Clear() method removed the values of the array, but didn’t erase the array. It is now an array with three null values. Just something to be aware of.
But while we are looking at arrays, let me give you another special operator, the single comma. The problem is you might have code like this:
You want to create an array like you did before instead $b is an integer. The , operator can solve that problem.
Now $b is automatically an array.
The last special operator I want to demonstrate is the subexpression or $(). Knowing how this works and when to use it indicates that you have moved beyond absolute PowerShell beginner.
Beginners will try to build a string like this:
"The computer $env:computername is running PowerShell version $psversiontable.psversion"
Beginners will expect this to show the PowerShell version, but instead they get a result like this:
The computer WIN81-ENT-01 is running PowerShell version System.Collections.Hashtable.psversion
That’s not what they expected. Instead they need to use a subexpression. Think of a subexpression like this: PowerShell will run the commands inside the parentheses and the $ sign tells PowerShell to treat the result like a temporary variable. Here is the correct solution using a subexpression:
"The computer $env:computername is running PowerShell version $($psversiontable.psversion)"
I use subexpressions, often in verbose messages in my scripts. Let’s revisit my New-Password function.
Function New-Password { [cmdletbinding()] Param([int]$Length = 7) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" Write-Verbose "[BEGIN ] Using Parameter set $($pscmdlet.ParameterSetName)" Write-Verbose "[BEGIN ] $env:computername $((Get-WmiObject Win32_operatingsystem).Caption) PS v$($PSVersionTable.PSVersion)" } #begin Process { Write-Verbose "[PROCESS] Creating password with length $length" -join (33..126 | Get-Random -count $length | foreach {$_ -as [char]} ) } End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end }
With subexpressions, I can include some useful information in my verbose output.
So if you are trying to nest some type of value or result and aren’t getting the results you expect, see if you need to use a subexpression. Once you get your head around this idea, I think you’ll use subexpressions often.
As with most PowerShell topics I cover, I encourage you to try them out on your own and don’t forget to read the associated PowerShell help topics.