![](/img/trans.png)
[英]Why is my try catch error passing as successful even with -ErrorAction Stop on?
[英]How can I use try... catch and get my script to stop if there's an error?
我试图让我的脚本在遇到错误时停止,并使用 try... catch 为我提供一种处理错误的简单方法。 我曾想过世界上最简单的事情,但我显然在做一些愚蠢的事情。 我已经阅读了几个小时,但我被卡住了,任何帮助都会非常方便,谢谢!
这是一些示例代码,我把 erroraction 放在了所有地方,似乎无法阻止该死的事情!
$ErrorActionPreference = "Stop"
try {
get-content "c:\GarbageFileName.txt" -ErrorAction stop
}
catch {
write-output "in catch, I want it to stop now"
}
write-output "try-catch finished, script is continuing"
第二天添加此文字*来自人们的精彩答案,我希望我可以选择 1 个以上的答案,或者有足够的声誉来投票给那些我不情愿没有选择作为答案的答案,或者以某种方式说声谢谢!
在try / catch控制的整体思路是,你告诉脚本做什么,如果遇到的不是抛出错误并停止脚本的默认操作终止错误。 如果您的 catch 块只是通过Write-Host向终端显示一条消息,那么这就是所有错误处理,脚本将从那里继续。 如果您考虑一下,如果在捕获到错误时自动停止脚本,它会部分地破坏try/catch的目的。
在catch块中, $_将被设置为 ErrorRecord 对象,表示来自try块的终止错误(与存储在$error[0] 中的错误相同)。 因此,结束脚本的最简单方法是重新抛出如果您没有使用try/catch就会抛出的错误:
try {
Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
# Custom action to perform before terminating
throw $_
}
或者,如果要显示自定义消息而不是默认的 ErrorRecord:
try {
Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
throw 'Custom error message'
}
或者,如果您想在完成自定义错误处理后退出而不向错误流抛出错误,则可以按照 Joost 的答案中的建议使用break 。
或者您可以变得更复杂并创建您自己的 ErrorRecord 对象。 你可以用它做很多事情,这是一个太大的话题,无法在这里全面涵盖,但你可以通过谷歌搜索System.Management.Automation.ErrorRecord获得有关语法的更多信息。 这是我的一个脚本中的一个示例,可帮助您入门(从执行$query变量中定义的 SQL 查询的函数针对 SQL Server 数据库):
} catch {
$ErrorRecord = New-Object System.Management.Automation.ErrorRecord(
(New-Object Exception("Exception executing the query: $($_.Exception.InnerException.Message)")),
$query,
[System.Management.Automation.ErrorCategory]::InvalidArgument,
$null
)
$ErrorRecord.CategoryInfo.Reason = $_.CategoryInfo.Reason;
$ErrorRecord.CategoryInfo.Activity = $_.InvocationInfo.InvocationName;
$PSCmdlet.ThrowTerminatingError($ErrorRecord);
}
一些注意事项:
[CmdletBinding()]
时才可用。 否则,您可以使用throw $ErrorRecord
来抛出您的自定义错误。 但是,如果您使用$PSCmdlet.ThrowTerminationError ,结果将更像 Cmdlet 风格。 ( throw将从生成错误的函数中吐出一行,而$PSCmdlet.ThrowTerminatingError将从使用该函数的调用上下文中给出行。很难以一种有意义的方式来描述而不过于详细,但如果你尝试一下,你就会明白我的意思。) 顺便说一句,设置$ErrorActionPreference = "Stop"
,然后使用-ErrorAction Stop
。 首选项变量为所有 cmdlet 设置默认操作,并且-ErrorAction开关覆盖特定 cmdlet 的默认操作,因此无需先指定默认值,然后使用-ErrorAction指定您刚刚设置为默认值的相同操作. 您可能想要做的只是省略$ErrorActionPreference = "Stop"
。
唯一缺少的是您在 Catch 块中的break
语句。 如果您不指示,Powershell 不会停止脚本。
try {
get-content "c:\GarbageFileName.txt" -ErrorAction stop
}
catch {
write-output "in catch, I want it to stop now"
break
}
write-output "try-catch finished, script is continuing"
还有一个小附录,以防万一它对您有所帮助:使用finally
,您可以添加一些始终执行的代码行,无论是否抛出异常。
try {
get-content "c:\GarbageFileName.txt" -ErrorAction stop
}
catch {
write-output "in catch, I want it to stop now"
break
}
finally {
#do some stuff here that is executed even after the break-statement, for example:
Set-Content -Path "f:\GarbageFileName.txt" -Value $null
}
#the line below is executed only if the error didn't happen
write-output "try-catch finished, script is continuing"
Try-Catch 将捕获一个异常并允许您处理它,也许处理它意味着停止执行......但它不会隐含地这样做。 它实际上会消耗异常,除非您重新抛出它。 但是您的问题比这更简单-ErrorAction stop
块优先于 get-content cmdlet 中的-ErrorAction stop
。 因此,您不会停止执行,而是进入Catch
块并继续执行,因为 catch 块中没有错误处理。
尝试从脚本中删除 try-catch 逻辑,并允许 cmdlet 出错:
get-content "c:\GarbageFileName.txt" -ErrorAction stop
write-output "You won't reach me if GarbageFileName doesn't exist."
并且您应该获得未达到write-output
所需的执行结果:
PS C:\> .\so-test.ps1
Get-Content : Cannot find path 'C:\GarbageFileName.txt' because it does not exist.
At C:\so-test.ps1:2 char:12
+ get-content <<<< "c:\GarbageFileName.txt" -ErrorAction stop
+ CategoryInfo : ObjectNotFound: (C:\GarbageFileName.txt:String) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.