关于 Trap

简短说明

描述处理终止错误的关键字。

详细说明

终止错误阻止语句运行。 如果 PowerShell 未以某种方式处理终止错误,PowerShell 还会停止在当前管道中运行函数或脚本。 在其他语言(如 C#)中,终止错误称为异常。

Trap 关键字指定要在发生终止错误时运行的语句列表。 Trap 语句处理终止错误,并允许脚本或函数的执行继续而不是停止。

Trap 语句也可能更复杂。 trap 的语句列表可以包含多个条件或函数调用。 陷阱可以写入日志、测试条件,甚至运行其他程序。

语法

Trap 语句的语法如下:

trap [[<error type>]] {<statement list>}

Trap 语句包括在发生终止错误时要运行的语句列表。 Trap 语句由关键字(可选)后跟类型表达式和语句块组成 trap ,该语句块包含在捕获错误时要运行的语句列表。 类型表达式优化了陷阱捕获的错误类型。

一个脚本或命令可以有多个 Trap 语句。 Trap 语句可以出现在脚本或命令中的任何位置。

捕获所有终止错误

当发生未在脚本或命令中以其他方式处理的终止错误时,PowerShell 会检查处理该错误的 Trap 语句。 如果存在 Trap 语句,PowerShell 将继续运行 Trap 语句中的脚本或命令。

以下示例是一个非常简单的 Trap 语句:

trap {"Error found."}

此 Trap 语句捕获任何终止错误。

在以下示例中,该函数包含导致运行时错误的无稽之谈字符串。

function TrapTest {
    trap {"Error found."}
    nonsenseString
}

TrapTest

运行此函数将返回以下内容:

Error found.

以下示例包括一个 Trap 语句,该语句使用 $_ automatic 变量显示错误:

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 then try
again.

重要

陷阱语句可以在给定范围内的任意位置定义,但始终适用于该范围内的所有语句。 在运行时,块中的陷阱是在执行任何其他语句之前定义的。 在 JavaScript 中,这称为 hoisting。 这意味着陷阱适用于该块中的所有语句,即使执行尚未超过定义它们的点。 例如,在脚本末尾定义一个陷阱并在第一个语句中引发错误仍会触发该陷阱。

捕获特定错误

一个脚本或命令可以有多个 Trap 语句。 可以定义陷阱来处理特定错误。

以下示例是捕获特定错误 CommandNotFoundException 的 Trap 语句:

trap [System.Management.Automation.CommandNotFoundException]
    {"Command error trapped"}

当函数或脚本遇到与已知命令不匹配的字符串时,此 Trap 语句将显示 “Command error trapped” 字符串。 运行 Trap 语句列表后,PowerShell 会将错误对象写入错误流,然后继续脚本。

PowerShell 使用 Microsoft .NET Framework 异常类型。 以下示例指定 System.Exception 错误类型:

trap [System.Exception] {"An error trapped"}

CommandNotFoundException 错误类型继承自 System.Exception 类型。 此语句捕获由未知命令创建的错误。 它还检测其他错误类型。

脚本中可以有多个 Trap 语句。 每种错误类型只能由一个 Trap 语句捕获。 发生终止错误时,PowerShell 会从当前执行范围开始搜索具有最具体匹配项的陷阱。

以下脚本示例包含错误。 该脚本包括一个常规 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 C:\temp\test\traptest.ps1: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 C:\temp\test\traptest.ps1:5 char:1
+ 1/$null
+ ~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException

尝试除以零不会产生 CommandNotFoundException 错误。 相反,该错误由另一个 Trap 语句捕获,该语句捕获任何终止错误。

捕获错误和范围

如果终止错误发生在与 Trap 语句相同的范围内,PowerShell 将运行陷阱定义的语句列表。 执行错误后的语句中会继续。 如果 Trap 语句与错误位于不同的范围内,则在与 Trap 语句位于同一范围内的下一个语句继续执行。

例如,如果函数中发生错误,并且 Trap 语句位于函数中,则脚本将在下一个语句中继续。 以下脚本包含一个 error 和一个 trap 语句:

function function1 {
    trap { "An error: " }
    NonsenseString
    "function1 was completed"
    }

稍后在脚本中,运行 Function1 函数将生成以下结果:

function1
An error:
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
then try again.
At C:\PS>TestScript1.ps1:3 char:19
+     NonsenseString <<<<

function1 was completed

函数中的 Trap 语句捕获错误。 显示消息后,PowerShell 将继续运行该函数。 请注意, Function1 已完成。

将此与以下示例进行比较,该示例具有相同的 error 和 Trap statement。 在此示例中,trap 语句发生在函数外部:

function function2 {
    NonsenseString
    "function2 was completed"
    }

trap { "An error: " }

function2

运行 Function2 函数将生成以下结果:

An error:
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
then try again.
At C:\PS>TestScript2.ps1:4 char:19
+     NonsenseString <<<<

在此示例中,未运行 “function2 was completed” 命令。 在这两个示例中,终止错误发生在函数中。 但是,在此示例中,Trap 语句位于函数外部。 PowerShell 在 Trap 语句运行后不会返回到函数。

谨慎

当为同一错误条件定义多个陷阱时,将使用按词法定义的第一个陷阱(范围内的最高)。

在以下示例中,仅运行具有 “whoops 1” 的 trap。

Remove-Item -ErrorAction Stop ThisFileDoesNotExist
trap { "whoops 1"; continue }
trap { "whoops 2"; continue }

break使用 and continue 关键字

您可以在 Trap 语句中使用 Break and Continue 关键字来确定脚本或命令在终止错误后是否继续运行。

如果您在 Trap statement 列表中包含语句 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:4 char:7

由于 Trap 语句包含关键字 Break ,因此函数不会继续运行,并且不会运行 “Function completed” 行。

如果在 Trap 语句中包含语句 Continue ,PowerShell 将在导致错误的语句之后恢复,就像没有 BreakContinue一样。 但是, Continue 使用关键字时,PowerShell 不会将错误写入错误流。

以下示例函数在 Continue 语句中使用 Trap 关键字:

function continue_example {
    trap {
        "Error trapped"
        continue
    }
    1/$null
    "Function completed."
}

continue_example
Error trapped
Function completed.

捕获错误后,函数将恢复,并运行 “Function completed” 语句。 没有错误写入错误流。

注释

trap 语句提供了一种简单的方法,可以广泛地确保处理作用域内的所有终止错误。 若要进行更精细的错误处理,请使用 try/catch 块,其中陷阱是使用 Catch 语句定义的。 Catch 语句仅适用于关联 Try 语句内的代码。 有关详细信息,请参阅 about_Try_Catch_Finally

另请参阅

about_Break

about_Continue

about_Scopes

about_Throw

about_Try_Catch_Finally