“I don’t always test my scripts, but when I do, I do it in production”

Don't lie. You've done it before. We all have at some point in time. It doesn't have to be risky though when running PowerShell scripts in production. Just remember to use the built-in PowerShell WhatIf parameter!

Wouldn't it be nice to know what that PowerShell command would do before it makes changes to your environment? Imagine being able to ask of your command, "What would you do if you were to run?" You can use the WhatIf parameter.

All compiled PowerShell cmdlets include a parameter called WhatIf. This parameter helps you evaluate if a command will work as you expect or if it will start a nuclear meltdown.

The handy WhatIf parameter is not only available with all built-in cmdlets but also to your scripts and advanced functions too! If your code will change things in your environment, you have the benefit of a fail-safe mechanism should you choose to implement it.

Prerequisites

This article is going to be a walkthrough. If you'd like to follow along during this journey, you should have a couple of things in place.

Note that in this article, I will be using Visual Studio Code 1.38 (August 2019) on a Windows 10 machine.

The WhatIf PowerShell Parameter: Defined

In a nutshell, the WhatIf parameter is a built-in switch parameter available with all advanced functions and cmdlets (by adding the PowerShell CmdletBinding keyword to scripts and functions). When used, the command reports the expected effect of the command to the console. But does not actually execute the command.

All cmdlets and advanced functions have the WhatIf parameter available. In this article, we'll demonstrate this parameter using the Get-Service, Stop-Service, and New-Item cmdlets.

Checking for WhatIf Support

If you are not sure whether a particular command supports WhatIf, there are two quick ways to check.

Using Get-Command

You can use the Get-Command command to view command metadata by using the Syntax parameter as shown below. If you see a -WhatIf reference, WhatIf is supported.

Get-Command <CommandName> -Syntax

Using Tab Completion

You can also check for WhatIf parameter support by using tab-completion. Simply type the command you'd like to check in a PowerShell console followed by a space, dash, 'Wh' and the tab key.

If WhatIf appears, you know that command has the WhatIf parameter.

PS> <CommandName> -Wh[tab]

Using the PowerShell WhatIf Parameter with Cmdlets

There are many different ways you can take advantage of the WhatIf parameter. In this section, you'll learn how you can begin to use the WhatIf parameter immediately using built-in cmdlets.

Creating a File

Like all cmdlets, the New-Item cmdlet has a WhatIf parameter. In this example, you will use the New-Item cmdlet to create a file named newfile1.txt in the same working directory.

If you were to run the below command, it would create the file called newfile.txt.

PS51> New-Item -ItemType File -Path .\newfile1.txt

But what if this command creates a file that may potentially cause a problem if were created unsuccessfully? No problem. You can add the WhatIf parameter to the end.

New-Item -ItemType File -Path .\newfile1.txt -WhatIf

Stopping a Service

You can also use the WhatIf parameter with the Stop-Service cmdlet. In this example, you’re getting a list of the first five services and stopping them with the Stop-Service command. But you're not.

Instead, you just seeing output message to the PowerShell console letting you know what services the Stop-Service cmdlet would have stopped.

PS51> (Get-Service)[0..4] | Stop-Service -WhatIf

Changing WhatIf Behavior Globally

At this point, you should know that using the WhatIf parameter with a cmdlet or advanced function only simulates the operation. You were affecting WhatIf behavior at the command-level.

The WhatIf behavior can also be set at a higher level that affects all commands by manipulating the automatic variable $WhatIfPreference.

The $WhatIfPreference variable is boolean. It can only be True or False. By default, it is set to False meaning WhatIf support is disabled on all commands unless overridden at the command-level. If set to True, all commands that support it, whether explicitly using the WhatIf parameter or not will be in "WhatIf mode."

You can test this by changing the value of $WhatIfPreference to True via $WhatIfPreference = $true. You can see below using New-Item without the WhatIf parameter now acts like the parameter was passed.

PS51> $WhatIfPreference = $true
If you've changed $WhatIfPreference to True, don't forget to change it back to False via $WhatIfPreference = $false.

In this section, you've learned how to use WhatIf support with existing cmdlets. In the next action, you’ll learn how to build WhatIf support in your custom scripts and functions.

Implementing WhatIf Support in Functions

Before you attempt to implement WhatIf support in your scripts, it is essential to know that there’s a wrong way and right way of doing it. You’ll see in the next sections what those are.

Doing it Wrong: Don't Reinvent the Wheel

It is not uncommon for script developers to reinvent the wheel and implement their own WhatIf support with some if/then logic. Below you can see an example.

Notice that the developer has defined their own WhatIf switch parameter. Then, using the value of that parameter, they then used an if/then construct to handle the logic when the WhatIf parameter was used or not.

Function Remove-LogFile {
    param (
        [Parameter(Mandatory)]
        [string]$name,

        [switch]$WhatIf
    )
    
    if ($WhatIf.IsPresent) { # WhatIf switch is on.
        Write-Host "WhatIf: I will remove the log file ""$name""" -ForegroundColor Yellow
    } else {
        # WhatIf switch is off.
        Write-Host "Delete log file ""$name""" -ForegroundColor Green
    }
}

When the above function is run using the WhatIf parameter as shown below, it looks like it did its job. The function didn't actually remove anything and return a message to the console.

PS51> Remove-LogFile -name log.txt -WhatIf

If it works, then what's wrong with this method? Because you are neglecting the built-in capabilities of an advanced function. You’ll need to build this functionality into every function you create instead of just focusing on what the command will do when it is turned off.

Instead, don't reinvent the wheel and use the SupportsShouldProcess keyword combined with the $PSCmdlet.ShouldProcess(). That's coming up.

Doing it Right: Using SupportsShouldProcess

All functions using the [CmdletBinding()] keyword make them "advanced". This keyword adds various capabilities to the function including WhatIf support.

All advanced functions support WhatIf functionality, but it's up to you to take advantage of it. To do so, you must use the SupportsShouldProcess keyword in between the [CmdletBinding()] parentheses first as shown below.

[CmdletBinding(SupportsShouldProcess)]

The function now allows you to call the ShouldProcess() method on the $PSCmdlet function variable to determine if the WhatIf parameter was passed to the function or not. When the WhatIf parameter is used, ShouldProcess() returns False. Otherwise, it will always return True.

Function Remove-LogFile {
    [cmdletbinding(SupportsShouldProcess)]
    param (
        [Parameter(Mandatory)]
        [string]$name
    )
    if ($PSCmdlet.ShouldProcess($name)) {
        ## The WhatIf parameter was not used. The function "should process as normal
        Write-Host "Delete log file ""$name""" -ForegroundColor Green
    } else {
        ## The WhatIf parameter was not used
    }
}
WhatIf Parameter Used ShouldProcess() Result
True False
False True

Now you can see below when Remove-LogFile is executed with the WhatIf parameter; it displays the same behavior as built-in cmdlets.

PS51> Remove-LogFile -name log.txt -WhatIf

Summary

In this article, you learned about the PowerShell WhatIf parameter. You should now understand how it works and what benefits it can bring.

You should also know not to reinvent the wheel the next time you need a failsafe for your PowerShell functions. Instead, leverage existing PowerShell WhatIf support!

Further Reading