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 : 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.
At line:3 char:5
+ nonsenseString
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (nonsenseString:String) []
, CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
以下示例包含一个 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 : 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.
At line:3 char:5
+ nonsenseString
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (nonsenseString:String) []
, CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
重要
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 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 line:1 char:1
+ nonsenseString
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (nonsenseString:String) []
, CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
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 : 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.
At line:5 char:1
+ nonsenseString}
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (nonsenseString:String) []
, CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
由于 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
Attempted to divide by zero.
At line:5 char:1
+ 1/$null}
+ ~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
尝试除以零不会创建 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!
Attempted to divide by zero.
At line:3 char:4
+ 1/$x
+ ~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
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 : 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.
At line:3 char:5
+ NonsenseString
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (NonsenseString:String) []
, CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
function1 was completed
函数中的 trap
语句会捕获错误。 显示消息后,PowerShell 将继续运行该函数。 请注意, Function1
在 trap
语句之后完成。
将此行为与以下示例进行比较,该示例具有相同的错误和 trap
语句。 在此示例中,trap
语句在函数外部发生:
function function2 {
NonsenseString
'function2 was completed'
}
trap { 'An error:' }
function2
运行 Function2
函数将产生以下结果:
An error:
NonsenseString : 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.
At line:2 char:5
+ NonsenseString
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (NonsenseString:String) []
, CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
在此示例中, 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
Attempted to divide by zero.
At line:6 char:5
+ 1/$null
+ ~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorR
ecordException
+ FullyQualifiedErrorId : RuntimeException
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。