我是C#开发人员,有时PowerShell会让我发疯。
我有以下代码:
$script:ErrorActionPreference = 'Stop'
try {
# Some code here
}
catch [Microsoft.PowerShell.Commands.WriteErrorException] {
# Print error messages (without stacktrace)
Write-Host -ForegroundColor Red $_.Exception.Message
exit 1
}
catch [System.Management.Automation.RuntimeException] {
# A thrown string
Write-Host -ForegroundColor Red $_.Exception.Message
Write-Host -ForegroundColor Red $_.ScriptStackTrace
exit 1
}
catch {
# Print proper exception message (including stack trace)
Write-Host -ForegroundColor Red "$($_.Exception.GetType().Name): $($_.Exception.Message)"
Write-Host -ForegroundColor Red $_.ScriptStackTrace
exit 1
}
这个想法基本上是:
Write-Error
的调用,请使用第一个catch块。 现在,我的问题是
Write-Error
和第一个catch块:Write-Error
块中调用try
,则执行第二个catch块(即使应该执行第一个catch块)。 Write-Error
,则使用正确的(第一个)catch块。 这是为什么?
我检查了
WriteErrorException
和RuntimeException
是否彼此继承:它们没有继承(两者都从SystemException
继承,但这无关紧要)。我还验证了PowerShell 5.1和PowerShell Core(6.0)的行为是否相同。
最佳答案
默认情况下,Write-Error
不会引发终止错误,但是正如您所提到的,它将ErrorActionPreference
设置为Stop
。但是,这将引发ActionPreferenceStopException
的异常继承为RuntimeException
您仍然可以在没有WriteErrorException
子句的情况下捕获RuntimeException
,因为ActionPreferenceStopException
的内部错误记录包含WriteErrorException
您可以通过运行以下命令了解我的意思:
Write-Error 'this is a test' -ErrorAction Stop
$error[0].ErrorRecord.Exception.GetType()
# IsPublic IsSerial Name BaseType
# -------- -------- ---- --------
# True True WriteErrorException System.SystemException
但是使用
RuntimeException
子句,它将首先被拾取,因为RuntimeException
是最接近的匹配异常类型。要解决此问题,您需要抛出更具体的异常或在
$_
子句中测试RuntimeException
。这是后者$script:ErrorActionPreference = 'Stop'
try {
# Some code here
}
catch [Microsoft.PowerShell.Commands.WriteErrorException] {
# Print error messages (without stacktrace)
Write-Host -ForegroundColor Red $_.Exception.Message
exit 1
}
catch [System.Management.Automation.RuntimeException] {
if ($_.Exception -is [Microsoft.PowerShell.Commands.WriteErrorException]) {
# Print error messages (without stacktrace)
Write-Host -ForegroundColor Red $_.Exception.Message
exit 1
}
# A thrown string
Write-Host -ForegroundColor Red $_.Exception.Message
Write-Host -ForegroundColor Red $_.ScriptStackTrace
exit 1
}
catch {
# Print proper exception message (including stack trace)
Write-Host -ForegroundColor Red "$($_.Exception.GetType().Name): $($_.Exception.Message)"
Write-Host -ForegroundColor Red $_.ScriptStackTrace
exit 1
}
您还可以添加
ActionPreferenceStopException
子句并在那里测试$_
。编辑:实际上,除非您真的想使用
Write-Error
,否则最好抛出类似于C#的异常。因此,请使用Write-Error
代替ojit_code:throw [System.InvalidOperationException]::new('This is my message')
关于powershell - 在PowerShell中执行错误的catch块执行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50424345/