PowerShell 错误变量丢失内容

PowerShell error variable loses the content

我有一个很大的项目,里面有很多功能。 只有 2 个问题:

  1. 关于错误处理的“最佳实践”是什么?要对每个函数使用本地处理,还是在主部分仅使用一个错误记录?
  2. 棘手的部分 (!),让我们来看看函数中奇怪的错误行为 F_XXX:只有 $_ 传递错误消息,$Error[0] 在这里是空的!奇怪的是,当我单独启动函数 F_XXX 时(从模块中删除),它的行为符合预期,这意味着: $Error[0] 返回错误。代码:

Blockquote

$ErrorActionPreference = "Stop"
Function F1
{
    try
    {
    # do something
    }
    catch
    {
        # 1. cascade Error to Main?
        # throw $Error[0].InnerException
        # or
        # local Error-Logging?
        write-MyErrorLogging -message $Error[0].InnerException
    }
}



Function F2
{
    try
    {
        # do something
    }
    catch
    {
        # 1. cascade Error to Main?
        # throw $Error[0].InnerException
        # or
        # local Error-Logging?
        write-MyErrorLogging -message $Error[0].InnerException
    }
}
Function F_XXXXXX
{
    try
    {
        cls
        write-host "The install data is copied.."
        $share = "\my_wrong_path\sql_sources\" 
        Copy-Item $share -Destination $installDrive -Force -Recurse
    }
    catch
    {
        $Error[0] #here is nothing!
        $null -eq $Error[0] # here true
        $_.Exception # only here the error-message: wrong path!
    }
}

Blockquote

# here Main
try
{
    F1
    F2
    F_XXXXXX
}
catch
{
    write-MyErrorLogging -message $Error[0].InnerException
}

Blockquote

  • catch内,最好避免$Error[0],给定手头的错误可靠地反映在 automatic $_ variable.

    • 如果您确实需要通过 automatic $Error variable 访问 previous 错误,请在模块 中使用 $global:Error -详情见底部。
  • 除非您需要在发生错误时执行 额外的 操作,否则您可以让 script-terminating(致命)错误(您的 $ErrorActionPreference = "Stop" 语句将代码中的 all 错误变成)冒泡调用堆栈,直到它被 try / catch statement 捕获,或者在没有捕获的情况下终止整个调用堆栈(即脚本及其调用者)。

    • 如果您确实需要执行其他操作,请使用 try / catch,并将操作放在 catch 块中(以及可能的清理操作 finally 块),然后是 re-throwing 错误,只需调用 throw 而不带参数 .

因此,您可以在脚本的 top-level 范围内使用 single try / catch 语句:

# Turn all errors in this and descendant scopes into
# script-terminating (fatal) ones.
$ErrorActionPreference = 'Stop'

# ... other function definitions, without try / catch

# Top-level code that calls the other functions and catches
# any errors.
try
{
    F1
    F2
    F_XXXXXX
}
catch
{
    write-MyErrorLogging -message $_.InnerException
}

模块中的automatic $Error variable

奇怪的是,至少达到 PowerShell 7.2.3(撰写本文时为当前版本):

  • 模块中发生的错误 - 就像模块外发生的错误一样 - 记录在 [=52= 中存在的 $Error 变量中]全局范围。

  • 然而,一个看似未使用,module-local复制 of $Error存在,shadows全局变量。

解决方法是在模块.

中使用use $global:Error

鉴于 module-local 副本似乎从未被触及并且没有明显的用途,该行为表明存在错误。