mercredi 24 janvier 2018

PowerShell module function does not inherit WhatIf

TL;DR: Why do module functions not inherit -WhatIf implicitly when called from a script?

It was my understanding that cmdlets and functions will inherit switches such as -WhatIf from a calling script, however I have seen behaviour that demonstrates this is not always the case. I have confirmed that the examples in How do you support PowerShell's -WhatIf & -Confirm parameters in a Cmdlet that calls other Cmdlets? work fine for me, but the problem seems to happen when my script is calling a function that is defined in a module.

In my case I have a script with a function defined locally (i.e. in the PS1) file. This script imports a script module. When I run my main script with the -WhatIf switch, the local function inherits the -WhatIf state but module functions do NOT exhibit the "WhatIf" behaviour, potentially disastrously.

If I call Show-WhatIfOutput with the -WhatIf switch set explicitly, it works as expected.

If I move the Call-ShowWhatIf function from the script to the module, and use Call-ShowWhatIf -WhatIf it works fine. That is, Show-WhatIfOutput does have -WhatIf set implicitly, but this is not a solution I can use in my real-world case.

Even more simply, if I enable SupportsShouldProcess on the main script, the same pattern emerges: the local function will inherit the switch; the module functions will now.

Why does the module function not inherit -WhatIf when called from the script?


Test code

Test-WhatIf.psm1

function Show-WhatIfOutput {
    [CmdletBinding(SupportsShouldProcess)]
    param(
    )

    Write-Host $MyInvocation.Line.Trim()

    if($PSCmdlet.ShouldProcess("My host","Display WhatIf text")){
        Write-Warning "This is not WhatIf text!"
    }

    Write-Host ("-"*40)
}

Test-WhatIf.ps1

Import-Module C:\Test-WhatIf.psm1 -Force

function Call-ShowWhatIf {
    [CmdletBinding(SupportsShouldProcess)]
    param(
    )

    Write-Host "$($MyInvocation.Line.Trim()) > " -NoNewline
    Show-WhatIfOutput

    Write-Host "$($MyInvocation.Line.Trim()) > " -NoNewline
    Show-WhatIfOutput -WhatIf
}

Write-Host ("-"*40)

Show-WhatIfOutput
Show-WhatIfOutput -WhatIf
Call-ShowWhatIf
Call-ShowWhatIf -WhatIf

Save both of these files to (say) C:\ and run the PS1 script. The output I receive is:

----------------------------------------
Show-WhatIfOutput
WARNING: This is not WhatIf text!
----------------------------------------
Show-WhatIfOutput -WhatIf
What if: Performing the operation "Display WhatIf text" on target "My host".
----------------------------------------
Call-ShowWhatIf > Show-WhatIfOutput
WARNING: This is not WhatIf text!
----------------------------------------
Call-ShowWhatIf > Show-WhatIfOutput -WhatIf
What if: Performing the operation "Display WhatIf text" on target "My host".
----------------------------------------
Call-ShowWhatIf -WhatIf > Show-WhatIfOutput
WARNING: This is not WhatIf text!
----------------------------------------
Call-ShowWhatIf -WhatIf > Show-WhatIfOutput -WhatIf
What if: Performing the operation "Display WhatIf text" on target "My host".
----------------------------------------

You can see that in the 2nd "block" of output I call the module function directly and get a WhatIf statement.

You can see that in the 5th "block" of output I call the module function from within the local Call-ShowWhatIf function, as get the warning to say that WhatIf was not set.

Aucun commentaire:

Enregistrer un commentaire