繁体   English   中英

如果出现错误,我如何使用 try...catch 并让我的脚本停止?

[英]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);
}

一些注意事项:

  • 您会看到,在创建我的自定义 ErrorRecord 时,我使用了$_ ,我刚才说它包含与在try块中捕获的终止错误相关联的 ErrorRecord 对象。 这个想法是自定义一些错误输出,同时通过将它们分配给自定义 ErrorRecord 的相应属性来使用默认 ErrorRecord 的部分。
  • $PSCmdlet仅在您在函数或脚本的开头声明[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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM