Use cases for the new null coalescing operator in PowerShell 7

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

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s