關於PowerShell錯誤處理的一些坑
測試代碼:
Write-Host '**********test ErrorActionPreference when run commands**********'
$ErrorActionPreference = 'Continue'
Write-Host '$ErrorActionPreference=''Continue'''
Get-ChildItem notexist
Write-Host 'good'
[System.IO.File]::ReadAllText('notexist')
Write-Host 'good'
1 / 0
Write-Host 'good'
Write-Error 'bad'
Write-Host 'good'
# 如果去掉下面這些注釋,腳本會在Get-ChildItem notexist處拋出異常並停止執行
# $ErrorActionPreference = 'Stop'
# Write-host '$ErrorActionPreference=''Stop'''
# Get-ChildItem notexist
# Write-Host 'good'
# [System.IO.File]::ReadAllText('notexist')
# Write-Host 'good'
# 1 / 0
# Write-Host 'good'
# Write-Error 'bad'
# Write-Host 'good'
Write-Host '**********test ErrorActionPreference when run commands with try/catch**********'
$ErrorActionPreference = 'Continue'
Write-host '$ErrorActionPreference=''Continue'''
try {
Get-ChildItem notexist
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
try {
[System.IO.File]::ReadAllText('notexist')
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
try {
1 / 0
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
try {
Write-Error 'bad'
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
$ErrorActionPreference = 'Stop'
Write-host '$ErrorActionPreference=''Stop'''
try {
Get-ChildItem notexist
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
try {
[System.IO.File]::ReadAllText('notexist')
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
try {
1 / 0
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
try {
Write-Error 'bad'
Write-Host 'good'
}
catch {
Write-Host "Exception: $_"
}
輸出:
**********test ErrorActionPreference when run commands**********
$ErrorActionPreference='Continue'
Get-ChildItem : 找不到路徑“C:\notexist”,因為該路徑不存在。
所在位置 C:\test.ps1:5 字符: 1
+ Get-ChildItem notexist
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\notexist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
good
使用“1”個參數調用“ReadAllText”時發生異常:“未能找到文件“C:\notexist”。”
所在位置 C:\test.ps1:7 字符: 1
+ [System.IO.File]::ReadAllText('notexist')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FileNotFoundException
good
嘗試除以零。
所在位置 C:\test.ps1:9 字符: 1
+ 1 / 0
+ ~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
good
C:\test.ps1 : bad
所在位置 行:1 字符: 1
+ .\test.ps1
+ ~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,test.ps1
good
**********test ErrorActionPreference when run commands with try/catch**********
$ErrorActionPreference='Continue'
Get-ChildItem : 找不到路徑“C:\notexist”,因為該路徑不存在。
所在位置 C:\test.ps1:32 字符: 5
+ Get-ChildItem notexist
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\notexist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
good
Exception: 使用“1”個參數調用“ReadAllText”時發生異常:“未能找到文件“C:\notexist”。”
Exception: 嘗試除以零。
C:\test.ps1 : bad
所在位置 行:1 字符: 1
+ .\test.ps1
+ ~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,test.ps1
good
$ErrorActionPreference='Stop'
Exception: 找不到路徑“C:\notexist”,因為該路徑不存在。
Exception: 使用“1”個參數調用“ReadAllText”時發生異常:“未能找到文件“C:\notexist”。”
Exception: 嘗試除以零。
Exception: bad
坑:
- $ErrorActionPreference是發生非終結性錯誤時,控制腳本執行行為的全局變量
- 錯誤分兩種:Terminating and non-terminating errors,終結性錯誤以及非終結性錯誤。通常情況下,異常都是終結性錯誤,終結性錯誤能被catch捕捉。但是,有些命令只會往輸出流中寫錯誤信息,但是卻不拋出異常,典型的例子就是Write-Error,這個時候產生的是非終結性錯誤,非終結性錯誤不能被catch捕捉。
$ErrorActionPreference = 'Continue'
情況下,執行腳本(無異常處理機制)時,前一條命令產生了非終結性錯誤,腳本不會停止執行。有異常處理機制時,catch會捕獲終結性錯誤的異常並處理,所以緊接着拋出異常的命令后面的命令不會再繼續執行。但是catch不會捕獲非終結性錯誤,所以緊接着產生非終結性錯誤的命令后面的命令會再繼續執行。$ErrorActionPreference = 'Stop'
情況下,一句話,無論產生的是終結性錯誤還是非終結性錯誤,腳本會立刻停止執行,但是如果有異常處理,那么進入catch中繼續執行。- 大部分內置的Cmdlet都是高級函數,可以通過指定-ErrorAction來重寫全局的
$ErrorActionPreference
。比如,在$ErrorActionPreference = 'Continue'
情況下,執行Write-Error 'message1' -ErrorAction 'Stop'; Write-Host 'message2'
,第二條Write-Host 'message2'
不會被執行,這是由於指定了-ErrorAction 'Stop'
,Write-Error
產生的不再是非終結性錯誤,而是終結性錯誤,會拋出異常,由於沒有異常處理機制,所以會立刻停止執行。