2013-10-09 40 views
5

我試圖讓我的腳本停止,如果它遇到錯誤,並使用try ... catch給我一個簡單的方法來處理錯誤。世界上最簡單的事情我曾想過,但我顯然在做一些愚蠢的事情。我已經閱讀了幾個小時,並且卡住了,任何幫助都會非常方便,謝謝!如何使用try ... catch並讓腳本在出現錯誤時停止?

下面是一些示例代碼,我把遍佈各處的錯誤,似乎無法阻止該死的事情!

$ErrorActionPreference = "Stop" 
try { 
    get-content "c:\GarbageFileName.txt" -ErrorAction stop 
} 
catch { 
    write-output "in catch, I want it to stop now" 
} 
write-output "try-catch finished, script is continuing" 

這段文字加次日* 從人們意想不到的答案,我希望我能多選1分的答案或有足夠的信譽來投票,我不情願地沒了那些」不要選擇作爲答案,要麼表示感謝!

+0

拋出你捕獲的異常嗎?我不知道PowerShell,但這是你會在Java中做什麼。 –

+0

在這種情況下,爲什麼不成功使用'Test-Path $ TargetFile'然後'get-content'? – Eris

回答

8

一個的try/catch控制的整體思路是,告訴腳本做什麼,如果它遇到終止錯誤,而不是拋出錯誤並停止的默認操作的腳本。如果您的catch塊只向寫入主機顯示一條消息給終端,那就是所有錯誤處理,並且腳本將從那裏繼續。如果你仔細想想,如果腳本在發現錯誤時自動停止,它將部分地挫敗try/catch的目的。

捕捉塊,$ _將被設定爲表示終止錯誤從嘗試塊(即獲取存儲在$錯誤[0]的相同)的ErrorRecord對象。因此,要結束腳本最簡單的方法是重新拋出,將被拋出的錯誤,如果你沒有使用的try/catch

try { 
    Get-Content "c:\GarbageFileName.txt" -ErrorAction stop 
} catch { 
    # Custom action to perform before terminating 
    throw $_ 
} 

或者,如果你想顯示自定義消息而不是默認ErrorRecord:

try { 
    Get-Content "c:\GarbageFileName.txt" -ErrorAction stop 
} catch { 
    throw 'Custom error message' 
} 

或者,如果你想你與你的自定義錯誤處理結束後,沒有出現任何的錯誤錯誤流,只是退出,你可以使用突破在Joost的的答案建議。

或者你可以得到更復雜的,並創建自己的ErrorRecord對象。有很多你可以用這個做的,這是一個太籠統的話題,但是你可以通過使用搜索引擎獲得更多關於句法的信息。下面是從我的一個腳本,讓你(從執行在$查詢變量定義對SQL Server數據庫的SQL查詢的功能)開始一個例子:

} catch { 
    $ErrorRecord = New-Object System.Management.Automation.ErrorRecord(
    (New-Object Exception("Exception executing the query: $($_.Exception.InnerException.Message)")), 
    $query, 
    [System.Management.Automation.ErrorCategory]::InvalidArgument, 
    $null 
) 
    $ErrorRecord.CategoryInfo.Reason = $_.CategoryInfo.Reason; 
    $ErrorRecord.CategoryInfo.Activity = $_.InvocationInfo.InvocationName; 
    $PSCmdlet.ThrowTerminatingError($ErrorRecord); 
} 

有兩點要注意:

  • 你會看到,在創建我的自定義ErrorRecord,我使用$ _,這是我剛纔說的包含由被夾在嘗試塊終止錯誤相關的ErrorRecord對象。這個想法是定製一些錯誤輸出,同時使用默認ErrorRecord的一部分,並將它們分配給自定義ErrorRecord的相應屬性。
  • $ PSCmdlet僅在函數或腳本的開頭聲明[CmdletBinding()]時可用。否則,您可以使用throw $ErrorRecord來拋出您的自定義錯誤。但是,如果使用$ PSCmdlet.ThrowTerminatingError,結果將會更加Cmdlet式樣。 (throw將從產生該錯誤的函數中吐出一行,而$ PSCmdlet.ThrowTerminatingError將給出您使用該函數的調用上下文中的行。很難用沒有意義的方式來描述過於複雜的,但如果你用它嘗試,你會明白我的意思。)

順便說一句,它是多餘的設置$ErrorActionPreference = "Stop",然後用-ErrorAction Stop。首選項變量爲所有cmdlet設置默認操作,並且交換機將覆蓋特定cmdlet的默認操作,因此不需要先指定默認操作,然後使用-ErrorAction指定與您剛纔相同的操作設置爲默認值。你可能想要做的只是省略$ErrorActionPreference = "Stop"

+0

哇,我不知道$ PSCmdlet.ThrowTerminatingError - 這絕對是我即將實施的東西。 確實非常有幫助的評論! – Joost

1

Try-Catch將捕獲一個異常並允許您處理它,也許處理它意味着停止執行......但它不會那麼隱式地執行。除非你重新拋出它,它實際上會消耗這個異常。但是,您的問題比這更簡單 - try塊優先於get-content cmdlet中的-ErrorAction stop。因此,不是停止執行,而是繼續執行Catch塊,因爲catch塊中沒有錯誤處理。

嘗試從你的腳本中刪除的try-catch邏輯,並允許該cmdlet錯誤了:

get-content "c:\GarbageFileName.txt" -ErrorAction stop 
write-output "You won't reach me if GarbageFileName doesn't exist." 

,你應該得到執行的期望的結果沒有達到write-output

PS C:\> .\so-test.ps1 
Get-Content : Cannot find path 'C:\GarbageFileName.txt' because it does not exist. 
At C:\so-test.ps1:2 char:12 
+ get-content <<<< "c:\GarbageFileName.txt" -ErrorAction stop 
    + CategoryInfo   : ObjectNotFound: (C:\GarbageFileName.txt:String) [Get-Content], ItemNotFoundException 
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand 
5

唯一缺少的是你的break-在Catch-block中的語句。如果您不指示它,Powershell不會停止腳本。

try { 
    get-content "c:\GarbageFileName.txt" -ErrorAction stop 
} 
catch { 
    write-output "in catch, I want it to stop now" 
    break 
} 
write-output "try-catch finished, script is continuing" 

而且小編,在情況下,它可以幫助你:與finally,你可以添加一些代碼行被始終執行,無論閹拋出異常與否。

try { 
    get-content "c:\GarbageFileName.txt" -ErrorAction stop 
} 
catch { 
    write-output "in catch, I want it to stop now" 
    break 
} 
finally { 
    #do some stuff here that is executed even after the break-statement, for example: 
    Set-Content -Path "f:\GarbageFileName.txt" -Value $null 
} 

#the line below is executed only if the error didn't happen 
write-output "try-catch finished, script is continuing"