How to properly use the -verbose and -debug parameters in a custom cmdlet How to properly use the -verbose and -debug parameters in a custom cmdlet powershell powershell

How to properly use the -verbose and -debug parameters in a custom cmdlet


$PSBoundParameters isn't what you're looking for. The use of the [CmdletBinding()] attribute allows the usage of $PSCmdlet within your script, in addition to providing a Verbose flag. It is in fact this same Verbose that you're supposed to use.

Through [CmdletBinding()], you can access the bound parameters through $PSCmdlet.MyInvocation.BoundParameters. Here's a function that uses CmdletBinding and simply enters a nested prompt immediately in order examine the variables available inside the function scope.

PS D:\> function hi { [CmdletBinding()]param([string] $Salutation) $host.EnterNestedPrompt() }; hi -Salutation Yo -VerbosePS D:\>>> $PSBoundParameters____________________________________________________________________________________________________PS D:\>>> $PSCmdlet.MyInvocation.BoundParametersKey Value                                                                                                                                                                                                           --- -----                                                                                                                                                                                                           Salutation Yo                                                                                                                                                                                                              Verbose   True                                                                                       

So in your example, you would want the following:

function DoStuff `{    [CmdletBinding()]    param ()    process    {      new-item Test -type Directory `        -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true)    }}

This covers -Verbose, -Verbose:$false, -Verbose:$true, and the case where the switch is not present at all.


Perhaps it sounds strange, but there isn't any easy way for a cmdlet to know its verbose or debug mode. Take a look at the related question:

How does a cmdlet know when it really should call WriteVerbose()?

One not perfect, but practically reasonable, option is to introduce your own cmdlet parameters (for example, $MyVerbose and $MyDebug) and use them in the code explicitly:

function DoStuff {    [CmdletBinding()]    param    (        # Unfortunately, we cannot use Verbose name with CmdletBinding        [switch]$MyVerbose    )    process {        if ($MyVerbose) {            # Do verbose stuff        }        # Pass $MyVerbose in the cmdlet explicitly        New-Item Test -Type Directory -Verbose:$MyVerbose    }}DoStuff -MyVerbose

UPDATE

When we need only a switch (not, say, a verbosity level value) then the approach with $PSBoundParameters is perhaps better than proposed in the first part of this answer (with extra parameters):

function DoStuff {    [CmdletBinding()]    param()    process {        if ($PSBoundParameters['Verbose']) {            # Do verbose stuff        }        New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true)    }}DoStuff -Verbose

It's all not perfect anyway. If there are better solutions then I would really like to know them myself.


There is no need. PowerShell already does this as the code below proves.

function f { [cmdletbinding()]Param()        "f is called"    Write-Debug Debug    Write-Verbose Verbose}function g { [cmdletbinding()]Param()     "g is called"    f }g -Debug -Verbose

The output is

g is calledf is calledDEBUG: DebugVERBOSE: Verbose

It is not done as direct as passing -Debug to the next cmdlet though. It is done through the $DebugPreference and $VerbrosePreference variables. Write-Debug and Write-Verbose act like you would expect, but if you want to do something different with debug or verbose you can read here how to check for yourself.