Words: 884
Time to read: ~ 4 minutes
Update: 29-Aug-2018 – Thanks to the good folks in reddit (u/TheIncorrigible1 & u/Ta11ow) who pointed out that Pause is a function, not an alias & a really cool addition to the confirm attribute. Also added the second step I left out of the 1st draft (oops).
As more and more companies are doing and should be doing, we’re creating scripts and automating things away.
Also, like more and more companies, we’re not the best at it just yet. We’re trying; we make mistakes but we aim to learn from them.
So when a call came to add a “safety-net”, a pause in a script so that the user knows what they’re changing, we originally went with using pause
.
Here’s why you should use the built in confirm
instead.
Pause
We’re only going to be dealing with numbers from 1 to 10.
Let’s start off simple and only use the pause
function:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Test-ManualPause | |
function Test-ManualPause { | |
[CmdletBinding()] | |
param( | |
[int[]]$Numbers | |
) | |
process { | |
foreach ($num in $Numbers) { | |
Pause | |
"Current number: [$num]" | |
} | |
} | |
} | |
Test-ManualPause –Numbers $Numbers | |
#endregion |

I mean, that’s fine and it does what it should BUT…
- We have no idea what we’re working on next, just “Press Enter to continue…:“
- Unless you KNOW that
Ctrl + C
cancels commands, there is no way to exit this. You’ll try to exit and end up processing what you don’t want to!
So we go back and try to fix the first point, how can we see what we are about to process?
Read-Host
We’re just going to change pause
to Read-Host
so we can specify the message. It’s not that big a deal really since if you run Get-Content function:pause
you can see that pause = Read-Host
!

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Test-ManualConfirm | |
function Test-ManualConfirm { | |
[CmdletBinding()] | |
param( | |
[int[]]$Numbers | |
) | |
process { | |
foreach ($num in $Numbers) { | |
Read-Host –Prompt "Are you sure you want to process: [$num]" | |
"Current number: [$num]" | |
} | |
} | |
} | |
Test-ManualConfirm –Numbers $Numbers | |
#endregion |

So now we know what we are working on BUT…
- Unless you KNOW that
Ctrl + C
cancels commands, there is no way to exit this. You’ll try to exit and end up processing what you don’t want to!
So we go back and try to give them a yes or no option.
Read-Host then some
This time we save what the users says to our Read-Host
, if they say yes (“Y”) then we continue, otherwise we stop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Test-ListeningConfirm | |
function Test-ListeningConfirm { | |
[CmdletBinding()] | |
param( | |
[int[]]$Numbers | |
) | |
process { | |
foreach ($num in $Numbers) { | |
$keepGoing = Read-Host "Are you sure you want to process: [$num] (Y/N)" | |
if ($keepGoing -eq 'Y') { | |
"Current number: [$num]" | |
} else { | |
break | |
} | |
} | |
} | |
} | |
Test-ListeningConfirm –Numbers $Numbers | |
#endregion |
So now we have given the option of Yes or No.
Then we get told that this is automation, right? They don’t want to say Yes every single time or No every single time. So now we have to add those options as well!
Yes, All, No, Exit
So now we have to check if the use says Yes, No, Exit, otherwise we default to All.
So we use Read-Host
and switch
(with the -regex
switch because we’ve had to give them full word options and they’re probably only going to say a single letter for what they want).
We also have to add a flag ($doAll
) and a check if it’s set or not for our “do all” option.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Test-YesAllConfirm | |
function Test-YesAllConfirm { | |
[CmdletBinding()] | |
param( | |
[int[]]$Numbers | |
) | |
process { | |
foreach ($num in $Numbers) { | |
if (-not $doAll) { | |
$keepGoing = Read-Host "Are you sure you want to process: [$num] (Yes, No, All (default), Exit)" | |
switch –Regex ($keepGoing) { | |
'Yes' { "Current number: [$num]" } | |
'No' { break } | |
'Exit' { return } | |
Default { | |
$doAll = $true | |
"Current number: [$num]" | |
} | |
} | |
} else { | |
"Current number: [$num]" | |
} | |
} | |
} | |
} | |
Test-YesAllConfirm –Numbers $Numbers | |
#endregion |
Finally it works… BUT…
- It’s 26 lines long for this piece of code. If we have multiple then this is going to blow up size wise, and
- There’s definitely more but I think I’ve gotten the point across (or I hope I have).
So let’s try and use what’s built in to PowerShell.
Confirm
It breaks down to 3 lines of code.
- In the
[CmdletBinding()]
attribute, we add aSupportsShouldProcess
& aConfirmImpact
and set it to a value of either Low, Medium, or High. I set it to High cause I want to see it. (Want to know why? Run thisGet-Help about_Preference_variables | More
and check out the “ConfirmPreference” section). - We wrap what we want to do in an
if
statement and use$PSCmdlet.ShouldProcess()
to specify our confirm “target”.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Test-Confirm | |
function Test-Confirm { | |
[CmdletBinding(SupportsShouldProcess, | |
ConfirmImpact = 'High')] | |
param( | |
[int[]]$Numbers | |
) | |
process { | |
foreach ($num in $Numbers) { | |
if ($PSCmdlet.ShouldProcess($num)) { | |
"Current numbers: [$num]" | |
} | |
} | |
} | |
} | |
Test-Confirm –Numbers $Numbers | |
#endregion |
Woah! Look at that!
3 lines; we get “Yes”, “Yes to all”, “No”, “No to all”, “Suspend”, and “Help”!
I don’t even know what suspend does so I checked it out. It actually pauses our script and we can check the current values of our variables. That’s super handy and we can just “exit
” back to our script.
I haven’t even checked out the Help option yet!
It’s actually so much simpler to use confirm! So much so that I actually feel bad for all the times that I didn’t use it and used Read-Host
instead!
UPDATE
I had actually been trying to think of a way to do this but couldn’t figure it out until u/Ta11ow pointed me to the online docs of the SupportProcess method. Thanks to that I now know how to create a custom message with Confirm!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Test-EditedConfirm | |
function Test-EditedConfirm { | |
[CmdletBinding(SupportsShouldProcess, | |
ConfirmImpact = 'High')] | |
param( | |
[int[]]$Numbers | |
) | |
process { | |
foreach ($num in $Numbers) { | |
if ($PSCmdlet.ShouldProcess("Guess what this does? [$num]", | |
"Are you sure you want to process: [$num]", | |
'STOP!')) { | |
"Current numbers: [$num]" | |
} | |
} | |
} | |
} | |
Test-EditedConfirm –Numbers $Numbers | |
#endregion |

So now even our confirm can be edited to our liking. I think that’s brilliant!
And in case you are wondering what the first option “Guess what this does?” do…

Congratulations! You’ve also just introduced -Whatif
as well 🙂
Overall
However, the main reason that you should start to use Confirm
instead of Pause
is that Confirm
can be turned off!
There’s no point automating away the manual tasks if you then go back in and create a human step again!
All we need to do is add a -confirm:$false
to our script and we can turn off the command and have our tests run as they should.
Automated & independent.
Luckily our scripts are in source control, please excuse me while I change them 🙂
https://serverfault.com/questions/718901/powershell-prompt-to-continue-execution-of-code/1015583#1015583?newreg=26883c4fda594844b2177d64cc354ca6
Write-Warning “This is only a test warning.” -WarningAction Inquire
WARNING: This is only a test warning.
Confirm
Continue with this operation?
[Y] Yes [A] Yes to All [H] Halt Command [S] Suspend [?] Help (default is “Y”):
Inquire
eh? Sounds good!I think this is pretty cool but, I can’t get “A” Yes to All to work if your script has multiple of these and if that doesn’t work, you script looks goofy, because it keeps asking even if they say “A”