Advanced Functions Part 2: ShouldProcess() in Your Script Cmdlets
Advanced functions' ability to behave almost exactly like a "real" cmdlet isn't limited to parameter binding. You can also take advantage of the common -verbose parameter. Simply output your verbose output this way:
May 17, 2010
Advanced functions' ability to behave almost exactly like a "real" cmdlet isn't limited to parameter binding. You can also take advantage of the common -verbose parameter. Simply output your verbose output this way:
Write-Verbose "Beginning query"
And when the shell's $VerbosePreference variable isn't set to "SilentlyContinue" ("Continue" will enable the output), you'll see your verbose output.
But let's do something cooler. Try this:
Get-Process | Stop-Process -whatif
And now this:
Get-Service | Stop-Service -confirm
(Um, answer "no" when it asks). Stop-Process and Stop-Service both support the -whatif and -confirm parameters, because the cmdlets attempt to modify the system. Any cmdlet - or advanced function - that is going to change something should specify an impact level of either Low, Medium, or High; if the cmdlet is run without the -whatif or -confirm parameters, it will still ask for confirmation if the specified impact level is higher than the shell's built-in $ConfirmPreference variable (which is usually "High"). Your advanced functions can declare their impact level by modifying the CmdletBinding() attribute:
Function Win32Restart-Computer {
[CmdletBinding(
SupportsShouldProcess=$true,
ConfirmImpact="High"
)]
The SupportsShouldProcess bit tells the shell that your function supports both -confirm and -whatif. The way you actually implement that support is to write conditional code around whatever dangerous stuff your cmdlet is planning to do:
if ($pscmdlet.ShouldProcess($computername)) {
get-wmiobject win32_operatingsystem -computername $computername |
invoke-wmimethod -name Win32Shutdown -argumentlist $_action
}
Using the $pscmdlet.ShouldProcess() method automatically invokes the -whatif or -confirm functionality. You pass in a description of what you're planning to modify; in this example, I passed in the $computername variable to indicate the computer I plan to reboot. If the function was run with -whatif, ShouldProcess() will display the "what if" statement and return False, so that your conditional code won't actually execute. If the function was run with -confirm, your conditional code will only run if the user responded with "Yes" or "Yes to All."
Here's a complete function, along with an example of how to use it at the bottom. Also notice the cool comment-based help - after pasting this into your shell, you can run "Help Win32Restart-Computer" to see the nicely-formatted help - and the cool -whatif and -confirm parameters in the parameter list!
function Win32Restart-Computer {
.SYNOPSIS
Restarts one or more computers using the WMI Win32_OperatingSystem method.
.DESCRIPTION
Restarts, shuts down, logs off, or powers down one or more computers. This
relies on WMI's Win32_OperatingSystem class. Supports common parameters
-verbose, -whatif, and -confirm.
.PARAM computername
One or more computer names to operate against. Accepts pipeline input ByValue
and ByPropertyName.
.PARAM action
Can be Restart, LogOff, Shutdown, or PowerOff
.PARAM force
$True or $False to force the action; defaults to $false
#>
[CmdletBinding(
SupportsShouldProcess=$true,
ConfirmImpact="High"
)]
param (
[parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[string[]]$computerName,
[parameter(Mandatory=$true)]
[string]
[ValidateSet("Restart","LogOff","Shutdown","PowerOff")]
$action,
[boolean]$force = $false
)
BEGIN {
# translate action to numeric value required by the method
switch ($action) {
"Restart" {
$_action = 2
break
}
"LogOff" {
$_action = 0
break
}
"Shutdown" {
$_action = 2
break
}
"PowerOff" {
$_action = 8
break
}
}
# to force, add 4 to the value
if ($force) {
$_action += 4
}
write-verbose "Action set to $action"
}
PROCESS {
write-verbose "Attempting to connect to $computername"
# this is how we support -whatif and -confirm
# which are enabled by the SupportsShouldProcess
# parameter in the cmdlet bindnig
if ($pscmdlet.ShouldProcess($computername)) {
get-wmiobject win32_operatingsystem -computername $computername | `
invoke-wmimethod -name Win32Shutdown -argumentlist $_action
}
}
}
'localhost','server1' | Win32Restart-Computer -action LogOff -whatif
About the Author
You May Also Like