Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

By default, any named function that has the [CmdletBinding()] attribute accepts the -debug and -verbose (and a few others) parameters and has the predefined $debug and $verbose variables. I'm trying to figure out how to pass them on to other cmdlet's that get called within the function.

Let's say I have a cmdlet like this:

function DoStuff() {    [CmdletBinding()]     PROCESS {       new-item Test -type Directory    } } 

If -debug or -verbose was passed into my function, I want to pass that flag into the new-item cmdlet. What's the right pattern for doing this?

like image 879
Micah Avatar asked Nov 29 '10 07:11

Micah


People also ask

How do you pass parameters in PowerShell script?

A default value will not work with a mandatory parameter. You can omit the =$true for advanced parameters of type boolean [Parameter(Mandatory)] . @Andrew First of all you have to change the type of the parameter to [string] . If you then want to pass a string as parameter you can use either ' or " .

How do I pass multiple parameters to a PowerShell script?

To pass multiple parameters you must use the command line syntax that includes the names of the parameters. For example, here is a sample PowerShell script that runs the Get-Service function with two parameters. The parameters are the name of the service(s) and the name of the Computer.

Which parameter is used in cmdlet?

Parameters can accept input directly from the command line, or from objects passed to the cmdlet through the pipeline, The arguments (also known as values) of these parameters can specify the input that the cmdlet accepts, how the cmdlet should perform its actions, and the data that the cmdlet returns to the pipeline.

How do I set parameters in PowerShell?

To create a parameter set, you must specify the ParameterSetName keyword of the Parameter attribute for every parameter in the parameter set. For parameters that belong to multiple parameter sets, add a Parameter attribute for each parameter set.


2 Answers

$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 -Verbose  PS D:\>>> $PSBoundParameters  ____________________________________________________________________________________________________ PS D:\>>> $PSCmdlet.MyInvocation.BoundParameters  Key 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.

like image 63
bwerks Avatar answered Sep 19 '22 15:09

bwerks


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.

like image 37
Roman Kuzmin Avatar answered Sep 18 '22 15:09

Roman Kuzmin