about_Try_Catch_Finally
简短说明
介绍如何使用 try
、 catch
和 finally
块来处理终止错误。
长说明
使用 try
、 catch
和 finally
块来响应或处理脚本中的终止错误。 语句 Trap
还可用于处理脚本中的终止错误。 有关详细信息,请参阅 about_Trap。
终止错误使语句停止运行。 如果 PowerShell 未以某种方式处理终止错误,PowerShell 也会停止使用当前管道运行函数或脚本。 在其他语言(如 C#)中,终止错误称为异常。
try
使用 块定义脚本的一个部分,你希望 PowerShell 在其中监视错误。 当块内 try
发生错误时,错误首先保存到 $Error
自动变量中。 然后,PowerShell 搜索一个 catch
块来处理错误。 try
如果语句没有匹配catch
的块,PowerShell 将继续在父范围中搜索相应的catch
块或Trap
语句。 catch
块完成后,如果没有找到适当的catch
块或Trap
语句,则运行该finally
块。 如果错误无法处理,则会将错误写入错误流。
块 catch
可以包含用于跟踪错误或恢复脚本预期流的命令。 块 catch
可以指定它捕获的错误类型。 语句 try
可以包含针对不同类型错误的多个 catch
块。
块 finally
可用于释放脚本不再需要的任何资源。
try
、 catch
和 finally
类似于 try
C# 编程语言中使用的 、 catch
和 finally
关键字。
语法
语句 try
包含一个 try
块、零个或多个 catch
块以及零个或一个 finally
块。 语句 try
必须至少有一个 catch
块或一个 finally
块。
下面显示了 try
块语法:
try {<statement list>}
关键字 try
后跟大括号中的语句列表。 如果在运行语句列表中的语句时发生终止错误,则脚本会将错误对象从 try
块传递到相应的 catch
块。
下面显示了 catch
块语法:
catch [[<error type>][',' <error type>]*] {<statement list>}
错误类型显示在括号中。 最外侧的括号指示 元素是可选的。
关键字 catch
后跟错误类型规范的可选列表和语句列表。 如果块中 try
出现终止错误,PowerShell 会搜索相应的 catch
块。 如果找到一个,则执行块中的 catch
语句。
块 catch
可以指定一个或多个错误类型。 错误类型是 Microsoft .NET Framework异常或派生自.NET Framework异常的异常。 块catch
处理指定.NET Framework异常类或派生自指定类的任何类的错误。
如果块 catch
指定错误类型,该块将 catch
处理该类型的错误。 catch
如果块未指定错误类型,该catch
块将处理块中try
遇到的任何错误。 语句 try
可以包含不同指定错误类型的多个 catch
块。
下面显示了 finally
块语法:
finally {<statement list>}
关键字 finally
后跟一个语句列表,该列表在每次运行脚本时都会运行,即使 try
语句运行时没有错误或语句中 catch
捕获了错误。
请注意,按 Ctrl+C 会停止管道。 发送到管道的对象不会显示为输出。 因此,如果包含要显示的语句(例如“最终块已运行”),则即使该块运行,按 Ctrl+C 后也不会显示该 finally
语句。
捕获错误
以下示例脚本显示了包含 try
块的 catch
块:
try { NonsenseString }
catch { "An error occurred." }
关键字 catch
必须紧跟块 try
或其他 catch
块。
PowerShell 无法将“NonsenseString”识别为 cmdlet 或其他项。 运行此脚本将返回以下结果:
An error occurred.
当脚本遇到“NonsenseString”时,会导致终止错误。 块 catch
通过在块内运行 语句列表来处理错误。
使用多个 catch 语句
语句 try
可以具有任意数量的 catch
块。 例如,以下脚本具有一个用于下载 MyDoc.doc
的块,并且它包含两个catch
try
块:
try {
$wc = new-object System.Net.WebClient
$wc.DownloadFile("http://www.contoso.com/MyDoc.doc","c:\temp\MyDoc.doc")
}
catch [System.Net.WebException],[System.IO.IOException] {
"Unable to download MyDoc.doc from http://www.contoso.com."
}
catch {
"An error occurred that could not be resolved."
}
第一个 catch
块处理 System.Net.WebException 和 System.IO.IOException 类型的错误。 第二 catch
个块未指定错误类型。 第二个 catch
块处理发生的任何其他终止错误。
PowerShell 按继承匹配错误类型。 块catch
处理指定.NET Framework异常类或派生自指定类的任何类的错误。 以下示例包含一个 catch
块,该块捕获了“找不到命令”错误:
catch [System.Management.Automation.CommandNotFoundException]
{"Inherited Exception" }
指定的错误类型 CommandNotFoundException 继承自 System.SystemException 类型。 以下示例还捕获了“找不到命令”错误:
catch [System.SystemException] {"Base Exception" }
此 catch
块处理“找不到命令”错误和继承自 SystemException 类型的其他错误。
如果指定错误类及其派生类之一,请将 catch
派生类的块放在常规类的 catch
块之前。
注意
PowerShell 将所有异常包装在 RuntimeException 类型中。 因此,指定错误类型 System.Management.Automation.RuntimeException 的行为与非限定的 catch 块的行为相同。
在 Try Catch 中使用陷阱
当块中定义了 的块Trap
try
中try
发生终止错误时,即使存在匹配catch
的块,语句也会Trap
获取控制权。
Trap
如果 位于高于 try
的块中,并且当前范围内没有匹配catch
的块,Trap
则 即使任何父范围都有匹配catch
的块,也会控制 。
访问异常信息
catch
在块中,可以使用 (也称为 $PSItem
)访问$_
当前错误。 对象的类型为 ErrorRecord。
try { NonsenseString }
catch {
Write-Host "An error occurred:"
Write-Host $_
}
运行此脚本将返回以下结果:
An Error occurred:
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.
还可以访问其他属性,例如 ScriptStackTrace、 Exception 和 ErrorDetails。 例如,如果我们将脚本更改为以下内容:
try { NonsenseString }
catch {
Write-Host "An error occurred:"
Write-Host $_.ScriptStackTrace
}
结果将类似于:
An Error occurred:
at <ScriptBlock>, <No file>: line 2
使用 finally 释放资源
若要释放脚本使用的资源,请在 和 catch
块后面try
添加块finally
。 finally
无论块是否遇到终止错误,块语句都会try
运行。 PowerShell 在脚本终止之前或当前块超出范围之前运行 finally
块。
finally
即使使用 CTRL+C 停止脚本,块也会运行。 finally
如果 Exit 关键字从块中catch
停止脚本,则块也会运行。