Search code examples
powershellpowershell-2.0powershell-cmdlet

How do you support PowerShell's -WhatIf & -Confirm parameters in a Cmdlet that calls other Cmdlets?


I have a PowerShell script cmdlet that supports the -WhatIf & -Confirm parameters.

It does this by calling the $PSCmdlet.ShouldProcess() method before performing the change.
This works as expected.

The problem I have is that my Cmdlet is implemented by calling other Cmdlets and the -WhatIf or -Confirm parameters are not passed along to the Cmdlets I invoke.

How can I pass along the values of -WhatIf and -Confirm to the Cmdlets I call from my Cmdlet?

For example, if my Cmdlet is Stop-CompanyXyzServices and it uses Stop-Service to implement its action.

If -WhatIf is passed to Stop-CompanyXyzServices I want it to also be passed to Stop-Service.

Is this possible?


Solution

  • After some googling I came up with a good solution for passing common parameters along to called commands. You can use the @ splatting operator to pass along all the parameters that were passed to your command. For example, if

    Start-Service -Name ServiceAbc @PSBoundParameters

    is in the body of your script powershell will pass all the parameters that were passed to your script to the Start-Service command. The only problem is that if your script contains say a -Name parameter it will be passed too and PowerShell will complain that you included the -Name parameter twice. I wrote the following function to copy all the common parameters to a new dictionary and then I splat that.

    function Select-BoundCommonParameters
    {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory=$true)]
            $BoundParameters
        )
        begin
        {
            $boundCommonParameters = New-Object -TypeName 'System.Collections.Generic.Dictionary[string, [Object]]'
        }
        process
        {
            $BoundParameters.GetEnumerator() |
                Where-Object { $_.Key -match 'Debug|ErrorAction|ErrorVariable|WarningAction|WarningVariable|Verbose' } |
                ForEach-Object { $boundCommonParameters.Add($_.Key, $_.Value) }
    
            $boundCommonParameters
        }
    }
    

    The end result is you pass parameters like -Verbose along to the commands called in your script and they honor the callers intention.