我在 Powershell 中了解 try-catch-finally,但是是否有类似于 Python 的“else”子句的东西,其中代码仅在没有错误的情况下运行?
我正在编写一个在经常出现故障的网站上使用 invoke-webRequest 的脚本。我使用 try-catch 来捕获 HTTP 错误。
我还希望只有在 invoke-webRequest 命令成功完成时才运行一段代码。
try{
invoke-WebRequest -URI 'http://flakywebsite.com/site1' -Method GET
invoke-WebRequest -URI 'http://flakywebsite.com/site2' -Method GET
invoke-WebRequest -URI 'http://flakywebsite.com/site3' -Method GET
}
catch{
"This line will execute only if there is an error in the try block"
}
else{
"This line will execute only if there is NOT an error in the try block"
}
finally{
"This code will run regardless of whether there is or is not an error in the try block."
}
我有这个解决方法。它使用 catch block 将通知附加到 $Error 变量:
try{
invoke-WebRequest -URI 'http://flakywebsite.com/site1' -Method GET
invoke-WebRequest -URI 'http://flakywebsite.com/site2' -Method GET
invoke-WebRequest -URI 'http://flakywebsite.com/site3' -Method GET
}
catch{
$Error.add("An error occurred in the try loop."}
}
if($Error[-1] -ne "An error occurred in the try loop."){
"This code will run only if there is NOT an error in the try block.
}
这行得通,但它非常丑陋。在 Powershell 中有没有更好的方法来做到这一点?
最佳答案
不,从 v7 开始,遗憾的是 PowerShell 不提供类似 Python 的 else
子句作为 try
的一部分/catch
陈述。
一种选择是将 only-if-not-catch 代码放在
try
的底部 block , 在可能失败的命令之后 - 见 Zafer Balkan's helpful answer .如果这是不希望的 , 我建议使用以下成语作为 解决方法 :
# Make sure that even normally non-terminating errors trigger the
# `catch` block below.
# Note that the *first* error that occurs in the `try` block
# will jump to the `catch` block right away - subsequent commands won't execute.
$ErrorActionPreference = 'Stop'
# Save the count of errors currently recorded in the automatic $Errors collection.
$errCountBefore = $Error.Count
try {
invoke-WebRequest -URI 'http://flakywebsite.com/site1' -Method GET
invoke-WebRequest -URI 'http://flakywebsite.com/site2' -Method GET
invoke-WebRequest -URI 'http://flakywebsite.com/site3' -Method GET
}
catch {
# Write a custom error to the $Error collection, as the *first*
# (most recent) item.
# Note: If you want the error to also *display*, use `-ErrorAction Continue`.
Write-Error -ErrorAction SilentlyContinue "An error occurred in the try loop: $_"
}
if ($errCountBefore -eq $Error.Count) { # No errors occurred.
"This code will run only if there is NOT an error in the try block."
}
注:如果您没有在
catch
中写入错误 block ,使用自定义 [bool]
变量如 $caught
您设置为 $true
在您的 catch
block ,然后测试 if (-not $caught)
.至于你尝试了什么 :
$Error.add("An error occurred in the try loop."}
你不应该直接写信给
$Error
(这使得以下几点没有实际意义:不要添加字符串,也不要附加到它存储的错误集合中),原因如下:$Error
就是所谓的automatic variable 在 PowerShell 中,这通常意味着 PowerShell 自己管理它 ,并且用户代码不应该直接修改它。关于
$Error
的唯一异常(exception)是你可能想清除迄今为止在 session 中累积的错误集合,使用 $Error.Clear()
否则,PowerShell 管理
$Error
如下:$Error
,按时间倒序排列(最近的在前)。-ErrorAction Ignore
调用的命令。和来自外部程序的 stderr 输出。 $Error
仅包含提供有关每个错误的结构化详细信息的错误记录对象(类型为 System.Management.Automation.ErrorRecord
的实例)。 因此,为了在
$Error
中记录错误,您需要执行所有代码是使用 Write-Error
将错误写入错误流,或使用 Throw
引发脚本终止错误声明 - PowerShell 会将每个错误包装在 System.Management.Automation.ErrorRecord
中如有必要,添加到 $Error
前面按时间倒序排列。
关于Powershell try-catch ...其他?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58346168/