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>}
关键字 (keyword) try
后跟大括号中的语句列表。 如果在运行语句列表中的语句时发生终止错误,脚本会将错误对象从 try
块传递到相应的 catch
块。
下面显示了 catch
块语法:
catch [[<error type>][',' <error type>]*] {<statement list>}
错误类型显示在方括号中。 最外面的方括号指示 元素是可选的。
关键字 (keyword) 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
关键字 (keyword) 后跟每次运行脚本时都会运行的语句列表,即使try
语句运行时未出错或语句中catch
捕获了错误也是如此。
请注意,按 Ctrl+C 会停止管道。 发送到管道的对象不会显示为输出。 因此,如果包含要显示的语句(例如“Finally block 已运行”),则即使块已运行,在按 Ctrl+C 后也不会显示该 finally
语句。
捕获错误
以下示例脚本显示了具有 try
块的 catch
块:
try { NonsenseString }
catch { "An error occurred." }
关键字 (keyword) 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 中使用陷阱
当在 块中try
定义了 的 块Trap
中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 关键字 (keyword) 停止块中的catch
脚本,则块也会运行。