共用方式為


about_Try_Catch_Finally

簡短描述

描述如何使用 trycatchfinally 區塊來處理終止錯誤。

完整描述

使用 trycatchfinally 區塊來回應或處理腳本中的終止錯誤。 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 區塊可用來釋放腳本不再需要的任何資源。

trycatchfinally 類似於 C# 程式設計語言中使用的 trycatchfinally 關鍵詞。

語法

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 + 會停止管線。 傳送至管線的物件將不會顯示為輸出。 因此,如果您包含要顯示的語句,例如「Finally block 已執行」,即使您按下 CTRL 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 區塊。 例如,下列腳本具有下載 tryMyDoc.doc 區塊,且包含兩個 catch 區塊:

try {
    $wc = New-Object System.Net.WebClient
    $wc.DownloadFile("https://httpbin.org/MyDoc.doc","C:\temp\MyDoc.doc")
} catch [System.Net.WebException],[System.IO.IOException] {
    "Unable to download MyDoc.doc from https://httpbin.org."
} catch {
    "An error occurred that could not be resolved."
}

第一個 catch 區塊會處理 System.Net.WebExceptionSystem.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 區塊中發生終止錯誤,且 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.

您可以存取其他屬性,例如 ScriptStackTraceExceptionErrorDetails。 例如,如果我們將腳本變更為下列專案:

try { NonsenseString }
catch {
    Write-Host "An error occurred:"
    Write-Host $_.ScriptStackTrace
}

結果會類似:

An Error occurred:
at <ScriptBlock>, <No file>: line 2

使用 finally 釋放資源

若要釋放腳本所使用的資源,請在 finallytry 區塊之後新增 catch 區塊。 不論 finally 區塊是否遇到終止錯誤,try 區塊語句都會執行。 PowerShell 會在腳本終止之前或目前區塊超出範圍之前執行 finally 區塊。

即使您使用 finally+ 來停止腳本,仍會執行 區塊。 如果 finally 關鍵詞在 exit 區塊內停止腳本,也會執行 catch 區塊。

在下列範例中,try 區塊會嘗試將檔案下載到 C:\temp 資料夾。 catch 區塊會處理下載期間發生的錯誤。 finally 區塊會處置 WebClient 物件,並在該物件存在時移除暫存盤。

try {
    $wc = New-Object System.Net.WebClient
    $tempFile = "C:\temp\MyDoc.doc"
    $wc.DownloadFile("https://httpbin.org/MyDoc.doc",$tempFile)
} catch [System.Net.WebException],[System.IO.IOException] {
    "Unable to download MyDoc.doc from https://httpbin.org."
} catch {
    "An error occurred that could not be resolved."
} finally {
    $wc.Dispose()
    if (Test-Path $tempPath) { Remove-Item $tempFile }
}

另請參閱