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
必須緊接在 區塊或其他catch
區塊之後try
。
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
的區塊,即使有任何父範圍具有相符catch
的區塊,Trap
也會控制 。
存取例外狀況資訊
在 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
最後使用 釋放資源
若要釋放腳本所使用的資源,請在 和 catch
區塊之後try
新增 區塊finally
。 finally
不論區塊是否遇到終止錯誤,try
區塊語句都會執行。 PowerShell 會在 finally
腳本終止之前或目前區塊超出範圍之前執行 區塊。
finally
即使您使用 CTRL+C 停止腳本,區塊仍會執行。 finally
如果 Exit 關鍵詞停止區塊內的catch
腳本,區塊也會執行。