Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

PowerShell Blogging Week: Supporting WhatIf and Confirm

Posted on April 2, 2015April 4, 2015

We hope you are enjoying this experiment in community blogging. In today's contribution I want to demonstrate how you can add support for WhatIf and Confirm to your advanced PowerShell functions. It is actually quite easy, especially if your function is simply calling other PowerShell commands that already support –Whatif and –Confirm. The recommended best practice is that if your function will do anything that changes something, it should support these parameters. Here's how.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

In your function you will need to use the cmdletbinding attribute and specify SupportsShouldProcess.

[cmdletbinding(SupportsShouldProcess)]

Beginning with PowerShell 3.0 this is all you need but you will see scripters explicitly setting this to $True.

[cmdletbinding(SupportsShouldProcess=$True)]

That's fine, although personally I find it redundant. If SupportsShouldProcess is listed then by default it is True. There is no need to explicitly set this to $False. Simply omit it. When you add this attribute, you will automatically get the –WhatIf and –Confirm parameters. The best part is that if your function is simply calling PowerShell cmdlets that already support –WhatIf, they will automatically inherit this setting. Here's a sample function.

#requires –version 4.0

Function Remove-TempFile {
[cmdletbinding(SupportsShouldProcess)]

Param(
[Parameter(Position=0)]
[ValidateScript({Test-Path $_})]
[string]$Path = $env:temp
)

#get last bootup time
$LastBoot = (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUptime
Write-Verbose "Finding all files in $path modified before $lastboot"

(Get-Childitem -path $path -File).Where({$_.lastWriteTime -le $lastboot}) | Remove-Item

} #end function

The function deletes all files from the %TEMP% folder that have a last modified time older than the last boot up time. As you can see in the help, PowerShell added the necessary parameters.

When I run the function with –Whatif it is passed on to Remove-Item.

It is really that easy. I also automatically get support for –Confirm.

Things gets a little trickier when you want to support WhatIf for a function where your commands don't natively recognize SupportsShouldProcess. This would be true of any .NET static method or even a command line tool you might be running, to name a few examples. To add your own support you need to invoke the built-in $PSCmdlet object and its ShouldProcess() method. Here's a simple example.

Function Set-Folder {
[cmdletbinding(SupportsShouldProcess)]

Param(
[Parameter(Position=0,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[Alias("pspath")]
[ValidateScript({Test-Path $_})]
[string]$Path=".")

Process {
$Path = (Resolve-Path -Path $Path).ProviderPath
if ($PSCmdlet.ShouldProcess($Path)) {
#do the action
$Path.ToUpper()
}
} #Process

} #end function

This function hypothetically is going to perform some action on a folder and I'm simply displaying the folder name in upper case. The important part is the If statement. This is the bare minimum that you need. If you specify –WhatIf you'll be prompted.

The operation will be the name of your script or function. The target is the ShouldProcess parameter value which in my example is the path. But you can provide more specific information by specifying ShouldProcess parameters for the target and action. Here's a revised function.

Function Set-Folder2 {
[cmdletbinding(SupportsShouldProcess)]

Param(
[Parameter(Position=0,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[Alias("pspath")]
[ValidateScript({Test-Path $_})]
[string]$Path=".")

Process {
$Path = (Resolve-Path -Path $Path).ProviderPath
if ($PSCmdlet.ShouldProcess($Path,"Updating")) {
#do the action
$Path.ToUpper()
}
} #Process

} #end function

You must have the code for ShouldProcess otherwise even if you set the cmdletbinding attribute, PowerShell won't know which commands need WhatIf. You can also have as many ShouldProcess statements as you need.

When it comes to confirmation, things get a little trickier and it might depend on what you really need. As you saw above, any cmdlet that supports –Confirm should automatically inherit the setting. This works because there is another cmdletbinding attribute called ConfirmImpact which has a default value of Medium. Other options are Low and High. My first function could also have been written like this:

[cmdletbinding(SupportsShouldProcess,ConfirmImpact="medium ")]

Confirmation happens by comparing the value of ConfirmImpact with the built-in $ConfirmPreference variable which has a default value of High. If the value of $ConfirmPreference is equal to or greater than ConfirmImpact, PowerShell will prompt for confirmation. Let's test this out.

Function Set-Folder6 {
[cmdletbinding(SupportsShouldProcess,ConfirmImpact="High")]

Param(
[Parameter(Position=0,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[Alias("pspath")]
[ValidateScript({Test-Path $_})]
[string]$Path="."
)
Begin {
Write-Verbose "Starting $($MyInvocation.Mycommand)"
} #begin

Process {
$Path = (Resolve-Path -Path $Path).ProviderPath
Write-Verbose "Processing $path"
if ($PSCmdlet.ShouldProcess($Path,"Updating")) {
#do the action
$Path.ToUpper()
} #ShouldProcess
} #Process

End {
Write-Verbose "Ending $($MyInvocation.Mycommand)"
} #end

} #end function

Notice that I am also using for WhatIf. In this function the ConfirmImpact is set to high which means PowerShell will always prompt.

If I edit the function and change to ConfirmImpact to Medium or Low, then PowerShell will only confirm if I ask.

You don't have to specify anything for cmdletbinding. If you know you always want confirmation you can do something like this:

Function Set-Folder4 {
[cmdletbinding()]

Param(
[Parameter(Position=0,
ValueFromPipeline,
ValueFromPipelineByPropertyName)]
[Alias("pspath")]
[ValidateScript({Test-Path $_})]
[string]$Path=".",
[switch]$Force
)

Process {
$Path = (Resolve-Path -Path $Path).ProviderPath
Write-Verbose "Processing $path"
if ($Force -OR $PSCmdlet.ShouldContinue("Do you want to continue modifying folder?",$path)) {
#do the action
$Path.ToUpper()
}
} #Process

} #end function

Notice the use of the ShouldContinue method. When I run this function, PowerShell will always prompt for confirmation.

I also added a switch parameter called Force so that if it is specified, the user is not prompted for confirmation.

The downside to this approach is that help doesn't show anything.

Perhaps in special cases this is what you want. Personally, I think you are better off using the cmdletbinding attributes as I did for my Set-Folder6 example.

Adding support for WhatIf and Confirm doesn't take much effort and it will take your advanced function to the next level.


This post is part of the PowerShell Blogging Week series on Windows PowerShell Advanced Functions, a series of coordinated posts designed to provide a comprehensive view of a particular topic.

Other articles in this series:

  • Standard and Advanced Functions by Francois-Xavier Cat
  • PowerShell Advanced Functions: Can we build them better? by Mike F. Robbins
  • Dynamic Parameters and Parameter Validation by Adam Bertram
  • Creating Help and Comments by June Blender
  • Try/Catch and Essential Error Handling by Boe Prox

We hope you found our work worth your time.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

7 thoughts on “PowerShell Blogging Week: Supporting WhatIf and Confirm”

  1. Pat Richard (@patrichard) says:
    April 2, 2015 at 11:27 am

    So, since SupportsShouldProcess is sufficient and doesn’t require the “= $True” part, what about SupportsPaging? Same?

    1. Jeffery Hicks says:
      April 2, 2015 at 12:12 pm

      Anything that can be specified like =$True or =$false doesn’t require the explicit assignment. Although there’s not penalty if you do.

  2. Pingback: #PSBlogWeek 4 – Supporting WhatIf and Confirm in Advanced Functions |
  3. Pat Richard (@patrichard) says:
    April 2, 2015 at 6:18 pm

    So not specifying it is the same as = $false, and specifying it is the same as = $true.

    1. Jeffery Hicks says:
      April 2, 2015 at 6:54 pm

      Yes, in v3 and later.

  4. Pingback: PowerShell Advanced Functions: Can we build them better? With parameter validation, yes we can! | Mike F Robbins
  5. Pingback: Free eBook on PowerShell Advanced Functions | Mike F Robbins

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d