Search code examples
powershellparameterspowershell-cmdlet

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?


Solution

  • 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.