关于PowerShell错误处理的一些坑

关于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产生的不再是非终结性错误,而是终结性错误,会抛出异常,由于没有异常处理机制,所以会立刻停止执行。
上一篇:IDA Python提取数据


下一篇:A. Nastia and Nearly Good Numbers【1000 / 思维 构造】