about_Trap
简短说明
描述处理终止错误的关键字。
长说明
终止错误阻止语句运行。 如果 PowerShell 不以某种方式处理终止错误,PowerShell 也会停止在当前管道中运行函数或脚本。 在其他语言(如 C#)中,终止错误称为异常。
trap
关键字指定要在发生终止错误时运行的语句列表。 trap
语句可以通过以下方式处理终止错误:
在处理
trap
语句块并继续执行包含trap
的脚本或函数后显示错误。 此选项为默认行为。注意
在从属脚本块(例如
if
语句或foreach
循环)中发生终止错误时,trap
块中的语句将运行,而从属脚本块外的下一个语句继续执行。在
trap
语句中使用break
显示错误并中止执行包含trap
的脚本或函数。在
trap
语句中使用continue
,不提示错误,而继续执行包含trap
的脚本或函数。
trap
的语句列表可以包含多个条件或函数调用。 trap
可以编写日志、测试条件甚至运行另一个程序。
语法
trap
语句具有以下语法:
trap [[<error type>]] {<statement list>}
trap
语句包含在发生终止错误时运行的语句列表。 trap
语句由 trap
关键字组成,可以选择性后接类型表达式,以及包含在捕获错误时要运行的语句列表的语句块。 类型表达式可优化 trap
捕获的错误类型。
脚本或命令可以有多个 trap
语句。 trap
语句可以在脚本或命令中的任何位置显示。
捕获所有终止错误
当在脚本或命令中以另一种方式处理终止错误时,PowerShell 会检查 trap
处理错误的语句。 如果存在 trap
语句,PowerShell 将继续在 trap
语句中运行脚本或命令。
以下示例是一个最小 trap
语句:
trap { 'Error found.' }
此 trap
语句会捕获任何终止错误。
在以下示例中,该函数包含导致运行时错误的无意义字符串。
function TrapTest {
trap { 'Error found.' }
nonsenseString
}
TrapTest
运行此函数将返回以下输出:
Error found.
nonsenseString:
Line |
3 | nonsenseString
| ~~~~~~~~~~~~~~
| The term 'nonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
以下示例包含一个 trap
语句,它使用 $_
自动变量显示错误:
function TrapTest {
trap { "Error found: $_" }
nonsenseString
}
TrapTest
运行此版本的函数将返回以下输出:
Error found: The term 'nonsenseString' 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.
nonsenseString:
Line |
3 | nonsenseString
| ~~~~~~~~~~~~~~
| The term 'nonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
重要
trap
语句可以在给定脚本块中的任何位置定义,但始终应用于该脚本块中的所有语句。 在运行时,块中的 trap
语句在执行任何其他语句之前定义。
在 JavaScript 中,这称为 hoisting。 这意味着, trap
即使执行未超过定义这些语句的点,语句也适用于该块中的所有语句。 例如,在脚本结束时定义 trap
并在第一个语句中抛出错误仍会触发该 trap
。
捕获特定错误
脚本或命令可以有多个 trap
语句。 可以定义 trap
来处理特定错误。
以下示例是一个捕获特定错误 commandNotFoundException 的 trap
语句:
trap [System.Management.Automation.CommandNotFoundException] {
'Command error trapped'
}
当函数或脚本遇到与已知命令不匹配的字符串时,此 trap
语句将显示该 Command error trapped
字符串。
运行 trap
语句列表后,PowerShell 会将错误对象写入错误流,然后继续脚本。
PowerShell 使用 .NET 异常类型。 以下示例指定 System.Exception 错误类型:
trap [System.Exception] { 'An error trapped' }
CommandNotFoundException 错误类型继承自 System.Exception 类型。 此语句捕获未知命令引发的任何错误。 它还会捕获其他错误类型。
可以通过检查错误对象来查找错误的异常类型。 以下示例演示如何获取会话中最后一个错误的异常全名:
nonsenseString
$Error[0].Exception.GetType().FullName
nonsenseString: The term 'nonsenseString' is not recognized as a name of a
cmdlet, function, script file, or executable program. Check the spelling
of the name, or if a path was included, verify that the path is correct
and try again.
System.Management.Automation.CommandNotFoundException
一个脚本中可以有多个 trap
语句。 只有一个 trap
语句可以捕获每个错误类型。 发生终止错误时,PowerShell 将搜索具有最具体匹配项的 trap
,从执行的当前脚本块开始。
以下脚本示例包含错误。 该脚本包括一个常规 trap
语句,用于捕获任何终止错误和指定 CommandNotFoundException 类型的特定 trap
语句。
trap { 'Other terminating error trapped' }
trap [System.Management.Automation.CommandNotFoundException] {
'Command error trapped'
}
nonsenseString
运行此查询会产生以下结果:
Command error trapped
nonsenseString:
Line |
5 | nonsenseString
| ~~~~~~~~~~~~~~
| The term 'nonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
由于 PowerShell 无法识别 nonsenseString
为 cmdlet 或其他项,因此它将返回 CommandNotFoundException 错误。 特定 trap
语句会捕获此终止错误。
以下脚本示例包含相同的 trap
语句,但具有不同的错误:
trap { 'Other terminating error trapped' }
trap [System.Management.Automation.CommandNotFoundException] {
'Command error trapped'
}
1/$null
运行此查询会产生以下结果:
Other terminating error trapped
RuntimeException:
Line |
5 | 1/$null
| ~~~~~~~
| Attempted to divide by zero.
尝试除以零不会创建 CommandNotFoundException 错误。 另一 trap
个语句捕获任何终止错误,将除以零错误捕获。
捕获脚本块中的错误
默认情况下,当终止错误抛出时,执行将传输到捕获语句。 在 trap
块运行后,控件将返回到错误位置之后的下一个语句块。
例如,当 foreach
语句中发生终止错误时,trap
语句将运行,并在 foreach
块之后的下一个语句(而不是 foreach
块内)继续执行。
trap { 'An error occurred!'}
foreach ($x in 3..-1) {
"1/$x = "
"`t$(1/$x)"
}
'after loop'
1/3 =
0.333333333333333
1/2 =
0.5
1/1 =
1
1/0 =
An error occurred!
RuntimeException:
Line |
4 | "`t$(1/$x)"
| ~~~~
| Attempted to divide by zero.
after loop
在输出中,可以看到循环会一直持续到最后一次迭代。 当脚本尝试将 1 除以 0 时,PowerShell 将引发终止错误。 该脚本跳过脚本块的 foreach
其余部分,运行 try
语句,并在脚本块之后 foreach
继续。
捕获错误和范围
如果终止错误发生在与 trap
语句相同的脚本块中,PowerShell 将运行由 trap
定义的语句列表。 执行错误后的语句中会继续。 trap
如果语句位于与错误不同的脚本块中,则执行将继续执行与该语句位于同一脚本块trap
中的下一个语句。
例如,如果在函数中发生错误,并且 trap
语句位于函数中,则脚本会在下一个语句中继续。 以下脚本包含错误和 trap
语句:
function function1 {
trap { 'An error: ' }
NonsenseString
'function1 was completed'
}
function1
运行此查询会产生以下结果:
An error:
NonsenseString:
Line |
3 | NonsenseString
| ~~~~~~~~~~~~~~
| The term 'NonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
function1 was completed
函数中的 trap
语句会捕获错误。 显示消息后,PowerShell 将继续运行该函数。 请注意, Function1
在 trap
语句之后完成。
将此行为与以下示例进行比较,该示例具有相同的错误和 trap
语句。 在此示例中,trap
语句在函数外部发生:
function function2 {
NonsenseString
'function2 was completed'
}
trap { 'An error:' }
function2
运行 Function2
函数将产生以下结果:
An error:
NonsenseString:
Line |
2 | NonsenseString
| ~~~~~~~~~~~~~~
| The term 'NonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
在此示例中, function2 was completed
命令未运行。 在这两个示例中,终止错误发生在函数中。 但在此示例中,trap
语句在函数外部。 PowerShell 在语句运行后 trap
不会返回到函数中。
注意
为相同的错误条件定义多个陷阱时,将使用第一个词法上定义的 trap
(脚本块中最高的)。
在以下示例中,仅运行 trap
with whoops 1
。
Remove-Item -ErrorAction Stop ThisFileDoesNotExist
trap { 'whoops 1'; continue }
trap { 'whoops 2'; continue }
重要
trap
语句的范围限定为编译位置。 如果在函数或点源脚本中具有 trap
语句,则当函数或点源脚本退出时,将删除内部的所有 trap
语句。
使用 break 和 continue 关键字
可以在 trap
语句中使用 break
和 continue
关键字来确定脚本或命令在终止错误后是否继续运行。
如果在 trap
语句列表中包含 break
语句,PowerShell 将停止函数或脚本。 以下示例函数在 trap
语句中使用 break
关键字:
function break_example {
trap {
'Error trapped'
break
}
1/$null
'Function completed.'
}
break_example
Error trapped
ParentContainsErrorRecordException:
Line |
6 | 1/$null
| ~~~~~~~
| Attempted to divide by zero.
trap
由于该语句包含break
关键字,因此该函数不会继续运行,并且Function completed
行未运行。
如果在 trap
语句中包含 continue
关键字,PowerShell 会在导致错误的语句后恢复,就像没有 break
或 continue
一样。 continue
但是,使用关键字时,PowerShell 不会将错误写入错误流。
以下示例函数在 trap
语句中使用 continue
关键字:
function ContinueExample {
trap {
'Error trapped'
continue
}
foreach ($x in 3..-1) {
"1/$x = "
"`t$(1/$x)"
}
'End of function'
}
ContinueExample
1/3 =
0.333333333333333
1/2 =
0.5
1/1 =
1
1/0 =
Error trapped
End of function
该函数在捕获错误后恢复,并且 End of function
语句运行。 没有错误写入错误流。
说明
trap
语句提供了一种方法来确保脚本块中的所有终止错误得到处理。 若要进行更精细的错误处理,请使用 try
/catch
块,其中陷阱是使用 catch
语句定义的。 catch
语句仅适用于关联 try
语句内的代码。 有关详细信息,请参阅 about_Try_Catch_Finally。