Welcome to MSDN Blogs Sign in | Join | Help

Supporting -Whatif, -Confirm, -Verbose – In SCRIPTS!

<This is a super-important issue so you should definitely start using this in your scripts that you share with others (that have side effects on the system).
Please try it out and blog about it to others so that it becomes a community norm.
Thanks-jps>

One of the greatest things about PowerShell is that when you use a Cmdlet which is going to have a side effect on the system, you can always type –Whatif, -Confirm or –Verbose. Sadly, you lose this option when it comes to scripts. Over time we want to makes scripts be the semantic equivalent of Cmdlets – that is to say that a Cmdlet is a Cmdlet independent of whether you implement it in C#, VB.NET or PowerShell. That said, it takes us a while to get releases out and it really torques me that most scripts don't support –Whatif, -Confirm, and –Verbose so I decided to do something about it. I wrote a PowerShell fuction, Should-Process, which helps you implement these in your scripts (this is very similar to how we do it in Cmdlets). First let me show you a script using it and a transcript of using that script. This is a script which stops all the running calc programs:

function Stop-Calc ([Switch]$Verbose, [Switch]$Confirm, [Switch]$Whatif)
{
$AllAnswer = $null
foreach ($p in Get-Process calc)
{ if (Should-Process Stop-Calc $p.Id ([REF]$AllAnswer) "`n***Are you crazy?" -Verbose:$Verbose -Confirm:$Confirm -Whatif:$Whatif)
{ Stop-Process $p.Id
}
}
}

Here is a transcript of using that function:

PS> calc;calc;calc
PS> Stop-Calc -Whatif
What if: Performing operation "Stop-Calc" on Target "436"
What if: Performing operation "Stop-Calc" on Target "3776"
What if: Performing operation "Stop-Calc" on Target "4104"
PS>
PS>
PS>
PS> Stop-Calc -Verbose
VERBOSE: Performing "Stop-Calc" on Target "436".
VERBOSE: Performing "Stop-Calc" on Target "3776".
VERBOSE: Performing "Stop-Calc" on Target "4104".
PS> calc;calc;calc
PS>
PS>
PS>
PS> Stop-Calc -Confirm
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Calc" on Target "4596".
***Are you crazy?
[Y] Yes [A] Yes to All [N] No [L] No to all [S] Suspend [?] Help (defau
lt is "Y"): n
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Calc" on Target "5492".
***Are you crazy?
[Y] Yes [A] Yes to All [N] No [L] No to all [S] Suspend [?] Help (defau
lt is "Y"): s
PS> gps calc

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
55 3 1252 5148 49 0.02 4596 calc
55 3 1248 4936 49 0.06 5492 calc
55 3 1248 5168 49 0.06 5588 calc


PS> exit
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Calc" on Target "5492".
***Are you crazy?
[Y] Yes [A] Yes to All [N] No [L] No to all [S] Suspend [?] Help (defau
lt is "Y"): l
PS>
PS>
PS>
PS> Stop-Calc -Confirm
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Calc" on Target "4596".
***Are you crazy?
[Y] Yes [A] Yes to All [N] No [L] No to all [S] Suspend [?] Help (defau
lt is "Y"): ?
Y - Continue with only the next step of the operation.
A - Continue with all the steps of the operation.
N - Skip this operation and proceed with the next operation.
L - Skip this operation and all subsequent operations.
S - Pause the current pipeline and return to the command prompt. Type "exit"
to resume the pipeline.
[Y] Yes [A] Yes to All [N] No [L] No to all [S] Suspend [?] Help (defau
lt is "Y"): a
PS>

Here is the function that makes this all possible:

Function Should-Process ($Operation, $Target, [REF]$AllAnswer, $Warning = "", [Switch]$Verbose, [Switch]$Confirm, [Switch]$Whatif)
{
# Check to see if "YES to All" or "NO to all" has previously been selected
# Note that this technique requires the [REF] attribute on the variable.
# Here is an example of how to use this:
# function Stop-Calc ([Switch]$Verbose, [Switch]$Confirm, [Switch]$Whatif)
# {
# $AllAnswer = $null
# foreach ($p in Get-Process calc)
# { if (Should-Process Stop-Calc $p.Id ([REF]$AllAnswer) "`n***Are you crazy?" -Verbose:$Verbose -Confirm:$Confirm -Whatif:$Whatif)
# { Stop-Process $p.Id
# }
# }
# }
if ($AllAnswer.Value -eq $false)
{ return $false
}elseif ($AllAnswer.Value -eq $true)
{ return $true
}



if ($Whatif)
{ Write-Host "What if: Performing operation `"$Operation`" on Target `"$Target`""
return $false
}
if ($Confirm)
{
$ConfirmText = @"
Confirm
Are you sure you want to perform this action?
Performing operation "$Operation" on Target "$Target". $Warning
"@
Write-Host $ConfirmText
while ($True)
{
$answer = Read-Host @"
[Y] Yes [A] Yes to All [N] No [L] No to all [S] Suspend [?] Help (default is "Y")
"@
switch ($Answer)
{
"Y" { return $true}
"" { return $true}
"A" { $AllAnswer.Value = $true; return $true }
"N" { return $false }
"L" { $AllAnswer.Value = $false; return $false }
"S" { $host.EnterNestedPrompt(); Write-Host $ConfirmText }
"?" { Write-Host @"
Y - Continue with only the next step of the operation.
A - Continue with all the steps of the operation.
N - Skip this operation and proceed with the next operation.
L - Skip this operation and all subsequent operations.
S - Pause the current pipeline and return to the command prompt. Type "exit" to resume the pipeline.
"@
}
}
}
}
if ($verbose)
{
Write-Verbose "Performing `"$Operation`" on Target `"$Target`"."
}

return $true
}

I'm including this as an attachment to this entry just in case you have any copy/paste issues.

Use this often – it works great.

BTW – this all depends upon a technique that is not well documented – the [REF] attribute on parameters. Yes – PowerShell supports reference parameters! This is how we can set a variable in the Should-Process function in a way that that change is seen in the parent's scope. We do that in order to handle the YES-TO-ALL/NO-TO-ALL feature. We need to change state and then see that change the next time we get called. Notice that this requires you to pass a reference variable using a very specific syntax ([REF]$AllAnswer). Then when we want to access this parameter, we have to access it's VALUE – e.g. $AllAnswer.Value . This deserves an entire blog entry for itself but I needed to use it here so I thought a quick explanation was in order.

Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.msp

Published Sunday, February 25, 2007 9:54 PM by PowerShellTeam

Attachment(s): should-process.ps1

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Pause

In the Newsgroup Microsoft.Public.Windows.PowerShell, BJ Stigall asked what the equivalent of the batch

Sunday, February 25, 2007 6:16 PM by Windows PowerShell

# re: Supporting -Whatif, -Confirm, -Verbose – In SCRIPTS!

Slowly.  Bit-by-bit.  We are getting all of your secrets.

Good blog.  Much good info beyond the purpose of the blog.

I like your statement about the treatment of CmdLets in any language.  It's gives us a little more fundamental knowledge about how PowerShell is intended to work and how it may change in the future.

Sunday, February 25, 2007 8:24 PM by jvierra

# Scripting XML Configuration Files

Those .NET XML Configuration files, you know the ones - web.config - app.config - thingy.exe.config -

Friday, April 27, 2007 4:49 PM by David Aiken

# re: Supporting -Whatif, -Confirm, -Verbose – In SCRIPTS!

I got interrupted.  I'll comment later.  picked up this link out of latest TechNET magazine - august.

 Greg McGlynn

Tuesday, July 31, 2007 1:54 PM by Greg McGlynn

# re: Supporting -Whatif, -Confirm, -Verbose – In SCRIPTS!

Thanks for this.  I took BASIC a long time ago on a Z80.  I didn't like it.  Powershell is what I've been waiting for.  Thank you for creating this.

Monday, August 06, 2007 8:20 PM by Greg McGlynn

# PowerShell Script for Setting Symbol Paths

In my continued resolution to make PowerShell my full time command line interface, I've been porting

Tuesday, January 22, 2008 5:21 PM by John Robbins' Blog

# Scripting Games 2008 Beginners Windows PowerShell Events 3 + 4

And I almost forgot the beginners events, not much special here : Event 3 d ir c:\scripts\*.txt |% {(get-content

Monday, February 25, 2008 4:24 PM by The PowerShell Guy

# re: Supporting -Whatif, -Confirm, -Verbose – In SCRIPTS!

Is there any plan to have BUILT-IN SUPPORT for this into v2 so we don't have to keep including this script everywhere?

Friday, August 01, 2008 12:29 PM by Joel "Jaykul" Bennett

# re: Supporting -Whatif, -Confirm, -Verbose – In SCRIPTS!

> Is there any plan to have BUILT-IN SUPPORT for this into v2 so we don't have to keep including this script everywhere?

Absolutely!  

jps

Friday, August 01, 2008 12:45 PM by PowerShellTeam

# PowerShell -whatif

PowerShell is Microsoft's new command line shell for Windows. Version 1 was released in 2006, and version 2 has been in CTP for about a year now; it will finally RTM with Windows 7. It's a truly fantastic shell, and if you haven't looked into it alread

Friday, February 27, 2009 8:01 PM by CodeBork

# PowerShell V2 介绍(6)- 高级函数(中)

在上次的介绍中我们主要介绍了Windows PowerShell V2 中高级函数的一些基础概念,在本次介绍中我们将要涉及的是如何使用高级函数达到类似cmdlet的使用体验(下面就以高级函数来称呼)。

Monday, May 18, 2009 10:56 AM by ghjconan's blog

Leave a Comment

(required) 
required 
(required) 
 
Page view tracker