PowerShell模块函数不继承WhatIf

Cha*_*ynt 8 testing powershell module function

-WhatIfTL;DR:为什么从脚本调用时模块函数不会隐式继承?

据我了解,cmdlet 和函数将继承诸如-WhatIf调用脚本之类的开关,但是我看到的行为表明情况并非总是如此。我已确认如何在调用其他 Cmdlet 的 Cmdlet 中支持 PowerShell 的 -WhatIf 和 -Confirm 参数?对我来说工作正常,但是当我的脚本调用模块中定义的函数时,问题似乎发生了。

就我而言,我有一个脚本,其中包含本地定义的函数(即在 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)
}
Run Code Online (Sandbox Code Playgroud)

测试-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
Run Code Online (Sandbox Code Playgroud)

将这两个文件保存到(例如)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".
----------------------------------------
Run Code Online (Sandbox Code Playgroud)

您可以看到,在输出的第二个“块”中,我直接调用模块函数并获得 WhatIf 语句。

您可以看到,在输出的第 5 个“块”中,我从本地Call-ShowWhatIf函数内调用了模块函数,因为收到警告说 WhatIf 未设置。

gms*_*man 4

调用者偏好变量不会从 传播Call-ShowWhatIfShow-WhatIfOutput。据我所知,这是从模块调用的函数的一个已知问题。在这种情况下,它$WhatIfPreference没有被传播。

将其添加到您的Show-WhatIfOutput应该可以解决问题:

if (-not $PSBoundParameters.ContainsKey('WhatIf'))
{
    $WhatIfPreference= $PSCmdlet.GetVariableValue('WhatIfPreference')
}
Run Code Online (Sandbox Code Playgroud)

它检查调用者( Call-ShowWhatIf) 是否已-WhatIf指定。当函数调用-WhatIf中未指定时,它会执行此操作(Show-WhatIfOutput )

这是一篇类似的帖子,描述了相同的问题但未-Verbose传播。

相关链接:
PowerShell.org - 脚本模块和变量作用域
脚本专家 - 周末脚本编写者:访问 PowerShell 首选项变量
TechNet - 从脚本模块函数的调用方导入首选项变量