如果出现错误,我如何使用 try...catch 并让我的脚本停止? [英] How can I use try... catch and get my script to stop if there's an error?

查看:88
本文介绍了如果出现错误,我如何使用 try...catch 并让我的脚本停止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让我的脚本在遇到错误时停止,并使用 try... catch 为我提供处理错误的简单方法.我曾想过世界上最简单的事情,但我显然在做一些愚蠢的事情.我已经阅读了几个小时但我被卡住了,任何帮助都会非常方便,谢谢!

I'm trying to get my script to stop if it hits an error, and use try... catch to give me an easy way to handle the error. The easiest thing in the world I'd have thought, but I'm obviously doing something stupid. I have read for a couple of hours and I'm stuck, any help would be very handy, thanks!

这是一些示例代码,我把错误操作放得到处都是,似乎无法阻止该死的东西!

Here's some example code, I've put erroraction all over the place, can't seem to stop the damn thing!

$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 个以上的答案,或者有足够的声誉来投票给那些我不情愿没有选择作为答案的答案,或者以某种方式说声谢谢!

this text added next day * Fantastic answers from people, I wish I could choose more than 1 answer or had enough reputation to vote for the ones which I reluctantly didn't choose as the answer, or say thanks somehow!

推荐答案

try/catch 控件的整个想法是告诉脚本如果它遇到一个终止错误,而不是抛出错误并停止脚本的默认操作.如果您的 catch 块只是通过 Write-Host 向终端显示一条消息,那么这就是所有错误处理,脚本将从那里继续.如果您考虑一下,如果在捕获到错误时自动停止脚本,它会部分违背 try/catch 的目的.

The whole idea of a try/catch control is that you tell the script what to do if it encounters a terminating error, instead of the default action of throwing the error and stopping the script. If your catch block just displays a message to the terminal with Write-Host, that's all the error handling there will be, and the script will continue from there. If you think about it, it would partially defeat the purpose of try/catch if the script were stopped automatically whenever an error is caught.

catch 块中,$_ 将设置为 ErrorRecord 对象,表示来自 try 块的终止错误(相同的存储在 $error[0] 中).因此,结束脚本的最简单方法是重新抛出如果您没有使用 try/catch 就会抛出的错误:

In the catch block, $_ will be set to the ErrorRecord object representing the terminating error from the try block (the same one that gets stored in $error[0]). So the simplest way to end the script is to rethrow the error that would have been thrown if you hadn't used a try/catch:

try {
  Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
  # Custom action to perform before terminating
  throw $_
}

或者,如果您想显示自定义消息而不是默认的 ErrorRecord:

Or, if you want to display a custom message instead of the default ErrorRecord:

try {
  Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
  throw 'Custom error message'
}

或者,如果您想在完成自定义错误处理后退出而不向错误流抛出错误,则可以按照 Joost 的回答中的建议使用 break.

Or you could use break as suggested in Joost's answer if you want to just quit after you're finished with your custom error handling without throwing an error to the error stream.

或者您可以变得更复杂并创建您自己的 ErrorRecord 对象.您可以用它做很多事情,这个话题太大,无法在此处全面涵盖,但您可以通过谷歌搜索 System.Management.Automation.ErrorRecord 获得有关语法的更多信息.这是我的一个脚本中的一个示例,可帮助您入门(从一个函数执行在 $query 变量中定义的 SQL Server 数据库中定义的 SQL 查询):

Or you could get more sophisticated and create your own ErrorRecord object. There's a lot you can do with that, it's too big a topic to cover comprehensively here, but you can get more info about the syntax by googling System.Management.Automation.ErrorRecord. Here's an example from one of my scripts to get you started (from a function that executes a SQL query defined in the $query variable against a SQL Server database):

} 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);
}

一些注意事项:

  • 您会看到,在创建我的自定义 ErrorRecord 时,我使用了 $_,我刚刚说过它包含与 try 中捕获的终止错误相关联的 ErrorRecord 对象 块.这个想法是自定义一些错误输出,同时通过将它们分配给自定义 ErrorRecord 的相应属性来使用默认 ErrorRecord 的部分.
  • $PSCmdlet 仅在您在函数或脚本的开头声明 [CmdletBinding()] 时才可用.否则,您可以使用 throw $ErrorRecord 来抛出您的自定义错误.但是,如果您使用 $PSCmdlet.ThrowTerminatingError,结果将更像 Cmdlet 风格.(throw 将从生成错误的函数中吐出该行,而 $PSCmdlet.ThrowTerminatingError 将从使用该函数的调用上下文中返回该行.它是很难以一种合理的方式来描述而不过于复杂,但如果你尝试一下,你就会明白我的意思.)
  • You'll see that in creating my custom ErrorRecord, I'm using $_, which I just said contains the ErrorRecord object associated by the terminating error that was caught in the try block. The idea is to customize some of the error output, while using parts of the default ErrorRecord by assigning them to the corresponding properties for the custom ErrorRecord.
  • $PSCmdlet is only available if you declare [CmdletBinding()] at the beginning of the function or script. Otherwise, you can just use throw $ErrorRecord to throw your custom error. However, the result will be more Cmdlet-style if you use $PSCmdlet.ThrowTerminatingError. (throw will spit back the line from the function that generated the error, whereas $PSCmdlet.ThrowTerminatingError will give you the line from the calling context where the function was used. It's hard to describe in a way that makes sense without getting too elaborate, but if you experiment with it you'll see what I mean.)

顺便说一句,设置$ErrorActionPreference = "Stop",然后使用-ErrorAction Stop 是多余的.首选项变量为所有 cmdlet 设置默认操作,-ErrorAction 开关覆盖特定 cmdlet 的默认操作,因此无需先指定默认值,然后使用 -ErrorAction 指定您刚刚设置为默认值的相同操作.您可能想要做的只是省略 $ErrorActionPreference = "Stop".

BTW, it's redundant to set $ErrorActionPreference = "Stop", and then use -ErrorAction Stop. The preference variable sets the default action for all cmdlets, and the -ErrorAction switch overrides the default action for a particular cmdlet, so there's no need to first specify the default, then use -ErrorAction to specify the same action you just set as the default. What you probably want to do is just leave out $ErrorActionPreference = "Stop".

这篇关于如果出现错误,我如何使用 try...catch 并让我的脚本停止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆