仅在 PowerShell 中捕获脚本终止错误

Catching script-terminating errors only in PowerShell

PowerShell 5.1

我编写了一个包装器脚本来启动另一个脚本,记录其输出(通过 Start-Transcript),如果它以非零代码退出则发送一封电子邮件,最后根据文件大小轮换日志文件.

我只想捕获会导致被调用脚本在其自身执行时退出的错误。 (脚本终止 术语基于此处的讨论:https://github.com/MicrosoftDocs/PowerShell-Docs/issues/1583)。

try { 
    Invoke-Expression "& '$Script' $ArgList"
    $err = $LastExitCode
} catch { 
    Write-Error -ErrorRecord $_
    $err = 1
}

抓住这个:

$ErrorActionPreference = 'Stop'
Remove-Item -Path DoesntExist

或者这个:

throw "Error"

但不是这个(脚本应该继续执行,如果不通过日志脚本调用的话):

Test-Path -Foo bar

可能吗?或者有更好的方法吗?

A try { ... } catch { ... } statement 不区分 语句 终止 (Test-Path -Foo bar) 和 脚本 -终止错误 (throw "Error"): both 终止 错误的子类型触发 catch块。

换句话说:任何本质上 语句 终止错误,例如 1 / 0Test-Path -Foo bar (调用语法错误,因为没有这样的参数)将总是 触发你的 catch 块。

任何非终止错误升级为脚本终止一个,使用 $ErrorActionPreference = 'Stop'-ErrorAction Stop(这是您想要的)。

  • 顺便说一句:$ErrorActionPreference = 'Stop' - 与 -ErrorAction Stop 不同 - 还会将 语句 终止错误提升为 脚本 -终止的,这只是 PowerShell 令人惊讶的复杂错误处理的问题方面之一,在您的问题中链接的 GitHub docs issue 中进行了详细讨论。

相关资料(不能解决你的问题):

关于post-mortem错误分析,最好分析是什么错误是通过检查 $_.Exception.WasThrownFromThrowStatement 来检查它是否是由 throw 语句 触发的脚本终止 ,但您通常无法区分一个语句终止错误、一个非终止错误和一个升级为脚本终止错误的非终止错误。

GitHub issue #4781 讨论了检测 内在 有效 错误“致命性”的潜在未来改进。