throw 和 $pscmdlet.ThrowTerminatingerror() 之间的区别是什么?

15

在PowerShell中,throw $ErrorMsg$PScmdlet.ThrowTerminatingError($ErrorMsg)有什么区别?

它们是相同的还是不同的?如果它们是不同的,哪一个更好?

1个回答

21

Throw会创建一个脚本(或者runspace)终止错误,而$PScmdlet.ThrowTerminatingError()会创建一个语句终止错误

注意:虽然这些不是官方术语(文档目前只含糊地提到了抽象的“终止”错误,没有范围),但它们有助于描述实际行为。

简而言之:

  • 一个脚本终止错误默认情况下会终止整个runspace,也就是运行中的脚本和所有调用者,并且没有进一步的语句会执行;换句话说:除非这样的错误被捕获或者被抑制,否则它是致命的

  • 一个语句终止错误仅会终止当前语句(调用$PScmdlet.ThrowTerminatingError()并且它是一个部分的语句,通常是一个管道),默认情况下执行将继续执行下一条语句.

    • 它们可以以与脚本终止错误相同的方式被捕获或抑制,但请注意,通用的-ErrorAction参数对它们没有影响.

    • 相反,您可以使用$ErrorActionPreference='Stop'将它们提升为脚本终止错误,尽管文档声称$ErrorActionPreference仅适用于非终止错误,即第三种错误类型(独占应用于-ErrorAction参数).

  • 有关更多信息,请参见此(非官方)PowerShell错误处理概述.

    至于何时使用哪种类型的错误的指导:

    • about_Throw帮助主题中,很少有关于何时使用Throw的指导;给出了一个示例用例,其中Throw用于在缺少强制参数时中止函数/脚本,作为替代PowerShell默认行为的提示

      • 请注意,即使没有捕获,也会终止整个运行空间(正在运行的脚本及其所有调用者)。
    • Cmdlet错误报告文章仅讨论与报告语句-终止(在该文章中称为“终止”)和非终止错误有关的命令-内部使用

      • 这篇文章的简洁摘要可以在此答案中找到。

    鉴于后者,您可以认为高级功能——因为它们像cmdlet一样——应该最多报告语句-终止错误,并且Throw脚本-终止错误)应该限于脚本,但请注意,这与使用Throw强制实施强制参数的用法相矛盾。

    也许在“脚本终止”和“语句终止”错误之间的棘手区别最终是无意的,而也许最初的意图只是有脚本终止错误,这就解释了为什么所有当前文档只谈论关于终止错误的概述,甚至没有提到这种区别。


    99%的时间我更喜欢使用脚本终止错误。这就是异常应该工作的方式。不过,我意识到,由于它是一个shell,有些情况可能只需要写入stderr,主要是在处理多个项目的管道情况下。但对我来说,那就是“例外”-双关语打趣一下 ;) - marsze
    1
    同意,@marsze。虽然官方不会承认,但我仍怀疑“语句终止错误”是一个意外,因为文档从未区分这两种终止错误的子类型。无论历史如何,对我来说,消除语句终止错误,只保留脚本终止错误是有道理的 - 但这不太可能发生。 - mklement0

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接