TL;DR:为什么模块函数在从脚本调用时不隐式继承 -WhatIf
?
据我了解,cmdlet 和函数将从调用脚本继承诸如 -WhatIf
之类的开关,但是我看到的行为表明情况并非总是如此。我已确认 How do you support PowerShell's -WhatIf & -Confirm parameters in a Cmdlet that calls other Cmdlets? 中的示例对我来说工作正常,但问题似乎发生在我的脚本调用模块中定义的函数时。
在我的例子中,我有一个脚本,其中包含一个在本地(即在 PS1 中)文件中定义的函数。该脚本导入一个脚本模块。当我使用 -WhatIf
开关运行我的主脚本时,本地函数继承了 -WhatIf
状态,但模块函数没有表现出“WhatIf”行为,这可能是灾难性的。
如果我调用 Show-WhatIfOutput
并显式设置了 -WhatIf
开关,它会按预期工作。
如果我将 Call-ShowWhatIf
函数从脚本移动到模块,并使用 Call-ShowWhatIf -WhatIf
它工作正常。也就是说,Show-WhatIfOutput
确实隐式设置了 -WhatIf
,但这不是我可以在实际案例中使用的解决方案。
更简单地说,如果我在主脚本上启用SupportsShouldProcess
,就会出现相同的模式:本地函数将继承开关;但是,模块功能不会。
为什么模块函数在从脚本调用时不继承-WhatIf
?
测试代码
测试-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)
}
测试-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
将这两个文件保存到(比方说)C:\
并运行 PS1 脚本。我收到的输出是:
----------------------------------------
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".
----------------------------------------
您可以看到,在输出的第二个“ block ”中,我直接调用模块函数并获得 WhatIf 语句。
您可以看到,在输出的第 5 个“ block ”中,我从本地 Call-ShowWhatIf
函数中调用了模块函数,因为得到了 WhatIf 未设置的警告。
最佳答案
来电者 Preference Variables不会从 Call-ShowWhatIf
传播到 Show-WhatIfOutput
。据我所知,这是从模块调用的函数的一个已知问题。在这种情况下,$WhatIfPreference
没有被传播。
将此添加到您的 Show-WhatIfOutput
应该可以解决问题:
if (-not $PSBoundParameters.ContainsKey('WhatIf'))
{
$WhatIfPreference= $PSCmdlet.GetVariableValue('WhatIfPreference')
}
它检查调用者 (Call-ShowWhatIf
) 是否指定了-WhatIf
。当函数调用 (Show-WhatIfOutput
)
-WhatIf
时,它会执行此操作
This is a similar post它描述了与 -Verbose
不传播相同的问题。
相关链接:
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
关于function - PowerShell 模块函数不继承 WhatIf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48421512/