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:

Don Jones

May 17, 2010

6 Min Read
ITPro Today logo in a gray background | ITPro Today

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


Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like