“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!
Not a reader? Watch this related video tutorial!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.
- A Windows computer capable of running Powershell v5.1. (Windows 10 and above recommended)
- A script editor like Notepad++, the Windows PowerShell ISE or Visual Studio Code.
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 Powershell 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.
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.
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.
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.
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.
Changing Powershell 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.
If you’ve changed
$WhatIfPreference
toTrue
, don’t forget to change it back toFalse
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 Powershell 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.
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 used. The function should NOT process.
}
}
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.
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!