我有一些像这样构建的代码
try{
...
}
finally{
...
<code that may throw>
}
当然,人们通常应该避免抛出最终的代码。但它可能发生。当它发生时,一个不幸的副作用是原始异常丢失。所以我在finally中要做的第一件事是关于try中抛出的异常的日志信息,如果抛出的话。
但是,我怎样才能确定在try块中是否确实发生了异常,一旦我在最后?有光滑的方式吗?我不想抓住捕获中的异常。我可以在try的末尾设置一个布尔值,这表示没有抛出异常,但我并不是每次都必须这样做的忠实粉丝。这看起来像这样:
$exceptionThrown = $true
try{
...
$exceptionThrown = $false
}
finally{
<if $exceptionThrown log info about it>
...
<code that may throw>
}
我可以做得更好吗?
答案 0 :(得分:1)
如果您避免使用 catch 块的唯一原因是因为您不想影响堆栈跟踪,则可以使用它,然后使用不带参数的 throw
重新抛出带有原始行号的错误;因此,就像您没有使用 catch 块一样重新抛出原始文件。例如:
$exceptionInfo = $null
try {
1/0 # cause some error
} catch {
$exceptionInfo = $_.Exception # you could set a flag / whatever here; without knowing your requirement I can't advise further
throw # you said you didn't want to catch it... but if you just don't want to impact the stack trace this is fine as we're rethrowing the original exception; not throwing a new one
} finally {
if ($null -eq $exceptionInfo) {
Write-Information 'Completed Successfully' -InformationAction Continue
} else {
Write-Warning "An error occurred $exceptionInfo"
}
}
如果您不想使用 catch 块并且不想使用您定义的某些变量来标记是否发生异常,您可以使用 $Error
;尽管您可能需要先清除它,因为它将包含当前会话中出现的所有错误...
$Error.Clear()
try {
1/0
} finally {
if ($Error.Count) {
Write-Warning "An error occurred $($Error[0])"
} else {
Write-Information 'Completed Successfully' -InformationAction Continue
}
}
通常你不需要确定某事是否在 finally 块中成功;而是:
throw
以便之后它仍然冒泡) .下面是一个粗略的说明;实际示例有点糟糕,因为我想不出一个好的和简洁的现实世界示例场景;但希望你能明白。
try {
$con = Get-MyDbConnection
New-DbRecord -Connection $con -Data $data
} catch {
Write-Log $_.Exception
} finally {
if (($null -ne $con) -and ($con.IsConnected)) {
$con.Disconnect()
}
}
答案 1 :(得分:0)
This page没有明确涵盖在“finally”块中抛出异常的情况,但是说Powershell行为类似于C#行为。接受this SO question about C# behavior的答案表明:
所以我认为你真正想要的是这样的:
try { ... set flag ... }
catch { ... adjust flag ... }
finally { ... check flag ... }
只有在“try”块中抛出异常时才会执行catch块,但是在每种情况下都会发生“finally”块(并且可以判断是否在原始“try”块中抛出了异常)检查标志的值。)
当然,如果可以在“finally”块中抛出异常并且您想要处理它,那么您将需要将整个业务包装在另一个“try”中。