如何将 -Verbose 传播到模块函数?

How to propagate -Verbose to module functions?

根据答案like this one和我自己的经验,Powershell 可以自动传播-Verbose(和-Debug),非常方便。然而,当我想要传播冗长的功能在一个模块中时,这将停止工作。用于测试的代码:

在某处创建一个名为Mod的目录,假设在c:,并添加2个文件:

文件c:\Mod\Functions.ps1:

function Show-VerbosityB { [cmdletbinding()]Param()
  Write-Output "Show-VerbosityB called"
  Write-Verbose "Show-VerbosityB is Verbose"
}

文件c:\Mod\Mod.psd1:

@{
ModuleVersion = '1.0.0.0'
NestedModules = @('Functions.ps1')
FunctionsToExport = @('*-*')
}

现在创建主脚本,比如 c:\Foo.ps1:

Import-Module c:\Mod

function Show-VerbosityA { [cmdletbinding()]Param()
  Write-Output "Show-VerbosityA called"
  Write-Verbose "Show-VerbosityA is Verbose"
}

function Show-Verbosity { [cmdletbinding()]Param()
  Write-Output "Show-Verbosity called"
  Write-Verbose "Show-Verbosity is Verbose"
  Write-Output "Testing propagation"
  Show-VerbosityA
  Show-VerbosityB
}

Show-Verbosity -Verbose

结果

PS> . C:\Foo.ps1
Show-Verbosity called
VERBOSE: Show-Verbosity is Verbose
Testing propagation
Show-VerbosityA called
VERBOSE: Show-VerbosityA is Verbose
Show-VerbosityB called

为什么跳过了模块函数中的 Write-Verbose,为什么传播的行为不像 Show-VerbosityA 那样? (如果我只是 dot-source Functions.ps1 而不是导入模块,则会打印行 VERBOSE: Show-VerbosityB is Verbose )。我可以通过例如制作传播手册打电话 Show-VerbosityB -Verbose:$PSBoundParameters['Verbose']。或者还有其他更短的方法吗?如果函数的行为因它们是模块的一部分还是点源而有所不同,那将是相当混乱的。

发生这种情况的原因是因为调用模块时 $VerbosePreference 没有传播。 我修改了您的脚本以在您通过 Write-VerboseWrite-Output.

输出的相同点显式打印值

This powershell.org post 建议将此添加到模块中,这对我来说就像一个魅力:

if (-not $PSBoundParameters.ContainsKey('Verbose'))
{
    $VerbosePreference = $PSCmdlet.GetVariableValue('VerbosePreference')
}

其中一条评论提到错误报告 link(它不存在或我没有查看权限)

问题 discussed in a TechNet post, with a link to a Get-CallerPreferance function 解决了这个问题。


模块:

function Show-VerbosityB { [cmdletbinding()]Param()

    <# uncomment to get verbose preference from caller, when verbose switch not explicitly used.
    if (-not $PSBoundParameters.ContainsKey('Verbose'))
    {
        $VerbosePreference = $PSCmdlet.GetVariableValue('VerbosePreference')
    }
    #>

    Write-Output "`nShow-VerbosityB called"
    Write-output "Global pref: $($global:VerbosePreference)"
    Write-output "Script pref: $($script:VerbosePreference)"
    Write-output "Effect pref: $VerbosePreference"
    Write-Verbose "Show-VerbosityB is Verbose"
}

来电:

Import-Module C:\Mod

Write-output "On startup: $VerbosePreference"

function Show-VerbosityA { [cmdletbinding()]Param()
  Write-Output "`nShow-VerbosityA called"
  Write-output "Global pref: $($global:VerbosePreference)"
  Write-output "Script pref: $($script:VerbosePreference)"
  Write-output "Effect pref: $VerbosePreference"
  Write-Verbose "Show-VerbosityA is Verbose"
}

function Show-Verbosity { [cmdletbinding()]Param()
  Write-Output "`nShow-Verbosity called"
  Write-output "Global pref: $($global:VerbosePreference)"
  Write-output "Script pref: $($script:VerbosePreference)"
  Write-output "Effect pref: $VerbosePreference"
  Write-Verbose "Show-Verbosity is Verbose"
  Write-Output "`nTesting propagation"
  Show-VerbosityA
  Show-VerbosityB
}

Show-Verbosity -Verbose

如果你想从调用者脚本中设置,试试这个:

(Get-Module 'ModuleName').SessionState.PSVariable.Set('Global:VerbosePreference', $VerbosePreference )