使用 $PSCmdlet.ThrowTerminatingError() 抛出错误的正确方法
使用 $PSCmdlet.ThrowTerminatingError() 抛出通用错误的正确方式是什么?
我对这个(可能有误的)理解是,在一个高级函数中,例如使用 CmdletBinding,我们应该更倾向于使用 $PSCmdlet.ThrowTerminatingError() 和 $PSCmdlet.WriteError(),而不是 throw 和 Write-Error。
然而,这些函数都无法接收像在 throw 和 Write-Error 中那样的简单字符串。它们需要一个 ErrorRecord。我发现构造一个 ErrorRecord 来抛出一个简单的错误非常繁琐,因为它们的构造函数都不接受字符串。
我为此绕过去的一个拙劣做法是像下面这样:
try {
throw 'An error occurred!'
} catch {
$PSCmdlet.ThrowTerminatingError($_)
}
但这看起来并不对劲。
处理这个问题的最佳方式是什么?
解决方案
甚至你提出的问题也可能得到基于观点的回答,我理解你之所以会质疑这一点,是因为 $PSCmdlet.ThrowTerminatingError() 指向调用处,而不是像 throw 和 Write-Error 那样指向你自己的脚本。也就是说,你把责任放在调用方,因此给它提供额外信息,如 errorId、errorCategory 和 targetObject,也不算坏事。这样调用方也可能有机会对问题进行编程层面的处理(前提是调用方不是一个以“简单字符串”为充分条件的LL M 😀)。
说实话,我也有同样的需求,至今一直在用一个函数来简化这个过程,但困难在于你会创建一个新的作用域,而这在你自行设计的 catch 上并非如此,另一方面,它相当冗长(与 throw 和 Write-Error 相比)。
不过还有一个 Trap 关键字,它很相似,但只需要设置一次。你甚至可以考虑仅 捕获特定错误,例如一个 ArgumentException(正如你所提问的地方最有可能的情况)。
或者创建一个自定义异常,这样你仍然可以 重新抛出 任何其他意外异常:
class CallerError : Exception {
CallerError($Message) : base($Message) { }
}
function a {
[CmdletBinding()]param()
Trap [CallerError] {
$PSCmdlet.ThrowTerminatingError($_)
}
Throw [CallerError]'In your dreams'
}
function b { a }
b
结果如下:
