首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么时候我应该使用Write-Error而不是抛出呢?终止性错误与非终止性错误

什么时候我应该使用Write-Error而不是抛出呢?终止性错误与非终止性错误
EN

Stack Overflow用户
提问于 2012-02-15 22:13:36
回答 6查看 173.5K关注 0票数 162

看着PoshCode,http://poshcode.org/3226上的Get-WebFile脚本,我注意到了这个对我来说很奇怪的装置:

代码语言:javascript
复制
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return

这是什么原因,而不是下面的原因?

代码语言:javascript
复制
$URL_Format_Error = [string]"..."
Throw $URL_Format_Error

或者更好:

代码语言:javascript
复制
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error

据我所知,你应该使用Write-Error来表示非终止错误,并抛出来表示终止错误,所以在我看来,你不应该在Write-Error之后再使用Return。有什么不同吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-02-15 22:38:49

如果要通知用户非严重错误,则应使用Write-Error。默认情况下,它所做的就是在控制台上以红色文本打印一条错误消息。它不会阻止管道或循环的继续。另一方面,Throw会产生所谓的终止错误。如果你使用throw,流水线和/或当前循环将被终止。实际上,除非您使用traptry/catch结构来处理终止错误,否则所有的执行都将终止。

有一件事需要注意,如果您将$ErrorActionPreference "Stop"设置为并使用Write-Error,它将生成一个终止错误

在您链接的脚本中,我们可以找到以下内容:

代码语言:javascript
复制
if ($url.Contains("http")) {
       $request = [System.Net.HttpWebRequest]::Create($url)
}
else {
       $URL_Format_Error = [string]"Connection protocol not specified. Recommended action: Try again using protocol (for example 'http://" + $url + "') instead. Function aborting..."
       Write-Error $URL_Format_Error
    return
   }

该函数的作者似乎希望停止该函数的执行,并在屏幕上显示一条错误消息,但不希望整个脚本停止执行。脚本作者可以使用throw,但这意味着在调用函数时必须使用try/catch

return将退出当前作用域,该作用域可以是函数、脚本或脚本块。最好用代码来说明这一点:

代码语言:javascript
复制
# A foreach loop.
foreach ( $i in  (1..10) ) { Write-Host $i ; if ($i -eq 5) { return } }

# A for loop.
for ($i = 1; $i -le 10; $i++) { Write-Host $i ; if ($i -eq 5) { return } }

两者的输出:

代码语言:javascript
复制
1
2
3
4
5

这里的一个问题是在ForEach-Object中使用return。它不会像预期的那样中断处理。

更多信息:

  • $ErrorActionPreference
  • try/catch
  • trap
  • throw
  • return
票数 207
EN

Stack Overflow用户

发布于 2016-10-10 06:08:43

重要信息: There 2 types of terminating errors,不幸的是,当前的帮助主题将它们混淆了

  • statement-terminating错误,在某些不可恢复的情况下由cmdlet报告,以及由发生.NET异常/a PS运行时错误的表达式报告;默认情况下,只有语句终止,脚本继续执行。

除非被捕获,否则它们将终止当前运行空间(线程);也就是说,如果为applicable).,则它们不仅终止当前脚本,还终止其所有调用者

有关PowerShell错误处理的全面概述,请参阅GitHub documentation issue #1583

这篇文章的其余部分主要关注非终止错误与语句终止错误。

为了补充现有的有用答案,重点关注问题的核心:How do you choose 是否report a statement-terminating or error

Cmdlet Error Reporting包含有用的指南;让我尝试一个实用摘要

non-terminating errors背后的一般思想是允许对大型输入集进行“容错”处理:未能处理输入对象的子集不应(默认情况下)中止整个可能长时间运行的过程,从而允许您检查错误,并在以后仅重新处理 failed 对象-正如在自动变量$Error中收集的错误记录所报告的那样。

如果您的cmdlet /高级函数为:NON-TERMINATING ,则

  • 会报告

错误

代码语言:javascript
复制
- **accepts MULTIPLE input objects**, via the pipeline input and/or array-valued parameters, AND
- **errors occur for SPECIFIC input objects**, AND
- **these errors DO NOT PREVENT PROCESSING of FURTHER input objects IN PRINCIPLE** (_situationally_, there may be no input objects left and/or previous input objects may already have been processed successfully). 
    - In advanced functions, use `$PSCmdlet.WriteError()` to report a non-terminating error (`Write-Error`, unfortunately, doesn't cause `$?` to be set to `$False` in the _caller's_ scope - see [GitHub issue #3629](https://github.com/PowerShell/PowerShell/issues/3629)).
    - _Handling_ a non-terminating error: `$?` tells you whether the most recent command reported _at least one_ non-terminating error. 
        - Thus, `$?` being `$False` can either mean that _any (nonempty) subset_ of input objects weren't properly processed, possibly the entire set.
        - Preference variable `$ErrorActionPreference` and/or common cmdlet parameter `-ErrorAction` can modify the behavior of non-terminating errors (only) in terms of error output behavior and whether non-terminating errors should be escalated to _script_-terminating ones.

  • all other cases.

中,

  • 报告错误

代码语言:javascript
复制
- Notably, **if an error occurs in a cmdlet / advanced function that only accepts a SINGLE or NO input object and outputs NO or a SINGLE output object or takes** _**parameter input only**_ **and the parameter values given prevent meaningful operation.** 
    - In advanced functions, you must use `$PSCmdlet.ThrowTerminatingError()` in order to generate a statement-terminating error.
    - Note that, by contrast, the `Throw` keyword generates a _script_-terminating error that aborts the _entire script_ (technically: the current _thread_).
    - _Handling_ a statement-terminating error: A `try/catch` handler or `trap` statement may be used (which _cannot_ be used with _non-terminating_ errors), but note that even _statement_-terminating errors by default do not prevent the rest of the script from running. As with _non-terminating_ errors, `$?` reflects `$False` if the previous statement triggered a statement-terminating error.

不幸的是,并非所有PowerShell自己的核心cmdlet都遵循这些规则

  • 虽然不太可能失败,但如果失败,New-TemporaryFile (PSv5+)将报告一个非终止错误,尽管它不接受管道输入并且只生成一个输出对象-然而,这至少在PowerShell Core7.0中已经得到纠正:请参见GitHub issue #4634.

  • Resume-Job的帮助声称传递不受支持的作业类型(例如使用Start-Job创建的作业,因为Resume-Job只适用于工作流作业)会导致终止错误,但从PSv5.1开始并非如此。
票数 24
EN

Stack Overflow用户

发布于 2012-02-15 22:37:10

Write-Error cmdlet和PowerShell中的throw关键字之间的主要区别在于,前者只是将一些文本打印到standard error stream (stderr),而后者实际上是终止正在运行的命令或函数的处理,然后由PowerShell通过向控制台发送有关错误的信息来处理。

您可以在您提供的示例中观察到这两者的不同行为:

代码语言:javascript
复制
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return

在本例中,添加了return关键字,以便在将错误消息发送到控制台之后显式停止脚本的执行。另一方面,在第二个示例中,由于终止是由throw隐式完成的,因此return关键字不是必需的

代码语言:javascript
复制
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9294949

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档