'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; however, the module functions will not.
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.
Solution 1:[1]
Caller Preference Variables are not propagated from Call-ShowWhatIf
to Show-WhatIfOutput
. AFAIK this is a known issue with functions called from a module. In this case, it's the $WhatIfPreference
that is not being propagated.
Adding this to your Show-WhatIfOutput
should resolve the issue:
if (-not $PSBoundParameters.ContainsKey('WhatIf'))
{
$WhatIfPreference= $PSCmdlet.GetVariableValue('WhatIfPreference')
}
It checks if the caller (Call-ShowWhatIf
) has -WhatIf
specified. It does this when -WhatIf
is not specified in the function call (Show-WhatIfOutput
)
This is a similar post which described the same issue with -Verbose
not propagating.
Related links:
PowerShell.org - Script Modules and Variable Scopes
Scripting Guy - Weekend Scripter: Access PowerShell Preference Variables
TechNet - Import Preference variables from the caller of a Script Module function
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | G42 |