【问题标题】:Why do proxy commands handle errors differently为什么代理命令处理错误的方式不同
【发布时间】:2020-03-11 16:48:08
【问题描述】:

有一段时间,我正在维护一个 PowerShell Join-Object cmdlet。
在这里,我使用默认参数创建了一些代理命令,如 FullJoin-ObjectMerge-ObjectInsert-Object,如下所述:Proxy Functions: Spice Up Your PowerShell Core Cmdlets.
(在早期版本中,我使用的别名可能会出现问题如果用户创建了自己的别名。)

除了主命令和代理命令之间的错误处理略有不同之外,一切都按预期工作......

取以下MVCE,基于以下函数:

Function Inverse([Int]$Number) {
    Rubbish
    Write-Output (1 / $Number)
}

(函数Rubbish不存在的地方)

比我创建一个名为Reverse0的代理函数:

$MetaData = [System.Management.Automation.CommandMetadata](Get-Command Inverse)
$Value = [System.Management.Automation.ProxyCommand]::Create($MetaData)
$Null = New-Item -Path Function:\ -Name "Script:Inverse0" -Value $Value -Force
$PSDefaultParameterValues['Inverse0:Number'] = 0    # (Not really required for reproducing the issue)

如果我运行原始函数Reverse 0,我会得到两个错误:

Rubbish : The term 'Rubbish' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:2 char:1
+ Rubbish
+ ~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Rubbish:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Attempted to divide by zero.
At line:3 char:1
+ Write-Output (1 / $Number)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException

如果运行代理命令Reverse0(或Reverse0 0),我只会得到第一个错误:

Rubbish : The term 'Rubbish' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:2 char:1
+ Rubbish
+ ~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Rubbish:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CommandNotFoundException

似乎$ErrorActionPreference 之类的东西发生了变化,但我检查了一下,这两个函数似乎都一样。

是否有不同行为的解释?
有没有办法让代理命令在错误处理方面与原始命令一样?

【问题讨论】:

    标签: powershell error-handling command


    【解决方案1】:

    [System.Management.Automation.ProxyCommand]::Create() 生成的代码目前存在(PowerShell Core 7.0.0-preview.5)缺陷

    它通过在其catch 块中使用throw 而不是$PSCmdlet.ThrowTerminatingError($_) 错误地将语句-终止错误传播为脚本-终止错误,从而导致函数立即中止。

    如果您手动更正这些调用,您的代理函数应该会按预期运行。

    this GitHub issue;链接的问题并非专门针对此行为,但更改已获批准,并且应该包含针对它的修复。

    具体而言,目前,您必须手动修复生成的代码

    • 找到所有看起来像这样的try / catch 语句:
        try {
            # ...
        } catch {
            throw
        }
    
    • 并将它们替换为:
        try {
            # ...
        } catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-06
      • 2013-02-13
      • 1970-01-01
      相关资源
      最近更新 更多