执行这样的脚本时:
nonexistingcommand
echo "Hello"
Run Code Online (Sandbox Code Playgroud)
我得到:
nonexistingcommand : The term 'nonexistingcommand' 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 D:\Playground\powershell\Test.ps1:2 char:1
+ nonexistingcommand
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (nonexistingcommand:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Hello
Run Code Online (Sandbox Code Playgroud)
所以看起来这CommandNotFoundException是一个非终止错误。那么为什么如果我
try {
nonexistingcommand
}
catch [System.Management.Automation.CommandNotFoundException] {
throw
}
echo "Hello"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它将退出并且不打印“Hello”。
这是为什么?
不幸的是,PowerShell 有两种类型的终止错误:
语句终止错误,默认情况下仅终止封闭的语句。
默认情况下,执行恢复,即使用下一条语句(echo "Hello"在您的情况下)
CommandNotFoundException是此类错误的一个实例。
相比之下,如果进一步的管道输入可用,非终止Get-ChildItem NoSuchDir, \错误甚至会继续处理原始语句(例如,针对不存在的目录发出非终止错误,NoSuchDir然后继续成功报告现有目录。\)
脚本终止(线程终止)错误,它终止封闭的脚本和整个调用堆栈。
throw语句触发的,而不是由二进制(编译的)cmdlet 触发的。该try { ... } catch { ... } finally { ... }语句不区分这两种子类型:它同时捕获它们。
catch块包含一个无参数throw语句,该语句隐式中继触发错误的错误,您实际上将语句终止错误转换为脚本终止错误,因此执行会在那里结束。同样,将$ErrorActionPreference首选项变量设置为会'Stop'导致所有类型的错误(由PowerShell命令发出)[1]),包括非终止错误,从而中止整体执行;换句话说:非终止错误和语句终止错误都会提升为脚本终止错误。
有关PowerShell 极其复杂的错误处理的全面概述,请参阅GitHub 文档问题 #1583。
[1] 至少在控制台(终端)中外部程序的本地前台调用中,stderr输出默认情况下不通过 PowerShell 的错误流路由,因此不受$ErrorActionPreference.
但是,在 PowerShell v7.1 及更低版本(包括在 Windows PowerShell 中)中,使用2>重定向确实会通过 PowerShell 的错误流路由 stderr,这可能会产生意外的副作用。该问题将在 v7.2 中修复。
请注意,该行为是 PowerShell主机特定的并且适用于主机ConsoleHost(用于$host获取主机信息)。其他主机仍然总是通过错误流路由 stderr,这显着影响远程处理和后台作业。
| 归档时间: |
|
| 查看次数: |
1408 次 |
| 最近记录: |