I was just watching the recent presentation from the Research Triangle PowerShell Users Group, in which there is a demo about the new null coalescing operator in PowerShell 7 (by the way you should really subscribe to their Youtube channel!).
And, someone asked what could be a use case for this operator.
I won’t explain in detail how the operator works because it is very well explained in the demo, and other bloggers have already written about it.
However, this could be a possible usage:
- Everything which should exist will be created if it does not already exist
- Everything which should be part of something will be added if it does not already belong to
Pre-tip
Line continuation is available after the double question mark ??
and I will use it in my examples.
For instance these pieces of code are equivalent:
'This is a very long text to make the line of code very long' ?? 'This part will not be displayed'
'This is a very long text to make the line of code very long' ?? 'This part will not be displayed'
Use case examples
Filesystem
If a file or folder does not exist, then it will be created.
(Get-Item -Path C:\SomeFolder -ErrorAction SilentlyContinue) ?? (New-Item -Path C:\SomeFolder -ItemType Directory)
Active Directory or local user accounts or group
If a user or group does not exist, then it will be created.
(Get-LocalUser -Name TestUser -ErrorAction SilentlyContinue) ?? (New-LocalUser -Name TestUser -Password (Read-Host -AsSecureString))
Group members
If an account is not a member of a group, then it will be added.
(Get-LocalGroupMember -Name Administrators -Member TestUser -ErrorAction SilentlyContinue) ?? (Add-LocalGroupMember -Name Administrators -Member TestUser)
Modules
If a module is not installed or loaded, then load it or install it.
(Get-Module -Name 'PSScriptTools' -ListAvailable) ?? (Install-Module -Name 'PSScriptTools') (Get-Module -Name 'PSScriptTools') ?? (Import-Module -Name 'PSScriptTools')
Note:
The PSScriptTools module is available on the PowerShell Gallery and maintained by Jeff HICKS.
File content
If a file does not contain a specific line, then it will be added.
(Select-String -Pattern '^\*\.log$' -Path .\.gitignore) ?? (Add-Content -Value '*.log' -Path .\.gitignore)
For those who are not used to regular expressions, here is a little explanation about the regular expression used by the Select-String
cmdlet:
^ #must match the beginning of the line \* #litteral asterisk \. #litteral dot log #the word log $ #must match the end of the line
Applications
If an application is not installed, then install it.
(Get-InstalledSoftware -Name Git) ?? (choco install git)
Note 1:
Get-InstalledSoftware
is a cmdlet from the PSSoftware module,available on the PowerShell Gallery, and maintained by Adam BERTRAM.
Note 2:
choco
is a command from the package manager named Chocolatey.
Permissions
If permission is missing, then add it.
(Get-NTFSAccess -Path 'C:\test' -Account 'MyAccount') ?? (Add-NTFSAccess -Path 'C:\test' -Account 'MyAccount' -AccessRights 'FullControl' -AccessType 'Allow' -AppliesTo 'ThisFolderSubfoldersAndFiles')
Note:
Get-NTFSAccess
and Add-NTFSAccess
are two cmdlets from the NTFSSecurity module,available on the PowerShell Gallery, maintained by Raimund ANDREE.
Firewall rules
If a firewall rule does not exist, then it will be created.
(Get-NetFirewallRule -Name TestRule) ?? (New-NetFirewallRule -Name TestRule -DisplayName TestRule -Enabled True -Action Allow -Direction Inbound -Protocol TCP -LocalPort 9999)
Post-tips
Cmdlets to avoid
You must ensure that the left part returns $null
if the desired object does not exist.
Thus you cannot use the Test-Path
cmdlet because, it will either return $true
or $false
, but never $null
.
And so should do all Test-… cmdlets.
The most appropriate cmdlets to use on the left side of the null coalescing operator are Get-… cmdlets.
That’s why the general PowerShell usage for the null coalescing operator would be:
((Get-...) ?? (New-...)
Or
((Get-...) ?? (Add-...)
Displaying errors and other messages
In my examples above, I use -ErrorAction SilentlyContinue
to avoid displaying error messages when the desired object is not found.
Don’t use expressions like [void]
, $Null=
or |Out-Null
to remove the output of the left part of the coalescing operator, because obviously it returns always $null
and the right part of the coalescing operator would never be executed.
The left part must return something when it is successful. This is how the coalescing operator works. Currently you cannot avoid an output on the left part. Maybe a futur improvement for a second coalescing operator, but a quiet one…?
On the other hand, while the left part always has to returns something in case of success, the right part can be quiet, or you can also choose to add a Verbose
mode.
This can be handy when you combine the Get-Item
(on the left) and the New-Item
(on the right) cmdlets, because both are returning the same result and you won’t know if the object already existed or if it has been created.
The -Not
operator
It would be tempting to use the -Not
operator on the left side of the coalescing operator.
For example, instead of creating a folder that does not exist, you want to remove an existing folder.
However, the opposite of $null
is $true
, but there is no way in PowerShell of making the opposite of something equal to $null
and, as a consequence, the right side of the coalescing operator would never be executed.
Thus the -Not
operator cannot be used on the left side of the coalescing operator, and as a consequence, there seems to be little place for a usage of Remove-… cmdlets on the right side.
More complex expressions
You are not limited to a single one liner inside either the left or right side of the coalescing operator, but you must wrap your code between curly braces { }
and preceded by an ampersand &
.
For example if you want to install a missing module and install it at the same time:
(Get-Module -Name PSScriptTools -ListAvailable) ?? ( &{ Install-Module -Name PSScriptTools Import-Module -Name PSScriptTools } )
Same applies if you want to use semi-colons ;
(Get-Module -Name PSScriptTools -ListAvailable) ?? (&{Install-Module -Name PSScriptTools; Import-Module -Name PSScriptTools})
Best practices
There seems to be a consensus inside the PowerShell community that the coalescent operator is considered as an alias for “if something is null then”, and as such should be used only in an interactive command-line and not inside scripts/functions/modules.
And you? Do you know some other use cases? Please share them in the comments below.
4 thoughts on “Use cases for the new null coalescing operator in PowerShell 7”