执行命令时如何忽略PowerShell中的特定错误?

时间:2019-02-06 08:45:10

标签: powershell error-handling powershell-v3.0

我知道ErrorAction的论点,还有$ErrorActionPreference$Error$的论点。

上下文

我想解决的问题是,当运行外部命令(例如choco或git)时,它至少在我的任务上下文中会给出应警告甚至不警告的错误。

由于退出代码的存在,PowerShell认为该结果在任何意义上都是错误,例如将红色写到输出等,这在我的任务上下文中是不希望的。

我可以使用-ErrorAction2> $null抑制这些命令的错误输出,但是我对使用特定命令完全消除任何错误感到沮丧。

我只想忽略那种已知的“对我来说这不是问题”类型的错误。

问题

有什么方法可以处理命令的错误,而忽略某些特定的错误,但是通常会处理所有其他错误情况?

2 个答案:

答案 0 :(得分:3)

  • 在常规控制台窗口 中,在PowerShell v3及更高版本中, stderr行的打印效果与标准输出行一样

    • 这是理想的,因为许多程序使用 stderr不仅报告真实错误,而且还报告不是数据的任何内容,例如状态消息

    • Stderr行(除非重定向,请参见下文)直接在控制台上打印(而stdout行则发送到PowerShell的成功输出流中,在那里它们可以收集在变量中,通过管道发送,或通过{ {1}} / >)。

  • 遗憾的是,即使在v5.1 中, PowerShell ISE 也可以中打印stderr行红色 ,格式与PowerShell错误相同。

      带有PowerShell扩展的
    • Visual Studio Code并没有这个问题,并且值得一游,因为将来所有的开发工作都将集中在此,并且考虑到它也可以与跨平台的PowerShell < em> Core 版。
  • 性能良好的控制台应用程序单独使用其退出代码表示成功(退出代码>>)与失败(任何)非零退出代码)。 PowerShell将最近调用的控制台应用程序的退出代码保存在其自动0变量中。

  • 顺便说一句:

    • 公用参数$LASTEXITCODE-ErrorAction 不能用于外部程序。
    • 相似地,自PowerShell v5.1 / PowerShell Core 6.2.0-preview.4起,偏好变量-ErrorVariable无效(由于<{3}},偶然除外) )。
    • $ErrorActionPreference / try不能用于检测和处理外部程序的故障。
    • 有关PowerShell的复杂错误处理规则的全面概述,请参见this bug

注意:我在下面的示例中使用以下外部命令,它们产生1行stdout和1行stderr输出(请注意,重定向catch>&2处理,而不是PowerShell,因为它位于cmd内部;它用于生成stderr输出):

'...'

通过非零退出代码(cmd /c 'echo stdout & echo stderr >&2' )使命令信号失败的变体:

exit 1

因此, 通常以下内容就足够

cmd /c 'echo stdout & echo stderr >&2 & exit 1' 

这会捕获变量$stdOut = cmd /c 'echo stdout & echo stderr >&2' # std*err* will print to console if ($LASTEXITCODE -ne 0) { Throw "cmd failed." } # handle error 中的 stdout 输出,并将 stderr 输出传递到控制台。


如果要收集以后 的stderr输出,并且仅在出现错误 时显示它们:< / p>

$stdout
  • 请注意$stdErr = @() # initialize array for collecting stderr lines. # Capture stdout output while collecting stderr output in $stdErr. $stdOut = cmd /c 'echo stdout & echo stderr >&2 & exit 1' 2>&1 | Where-Object { $fromStdErr = $_ -is [System.Management.Automation.ErrorRecord] if ($fromStdErr) { $stdErr += $_.ToString() } -not $fromStdErr # only output line if it came from stdout } # Throw an error, with the collected stderr lines included. if ($LASTEXITCODE -ne 0) { Throw "cmd failed with the following message(s): $stdErr" } 重定向,它指示PowerShell通过以下方式通过管道(流2>&1,成功流)发送stderr行(流2,错误流)。好吧。

  • 1块中,Where-Object用于标识 stderr 行,因为PowerShell会将此类行包装在该类型的实例中。

    < / li>

或者,您可以将stderr输出收集到临时文件$_ -is [System.Management.Automation.ErrorRecord])中,读取其内容,然后将其删除。

this GitHub docs issue建议引入在变量中收集重定向的stderr输出的选项,类似于您可以如何请求 cmdlet 通过通用收集变量中的错误的方法参数
2>/path/to/tmpfile

有两个腔室

  • 从本质上讲,仅打印stderr行以后,相对于 stdout 输出的特定上下文可能会丢失。

  • 由于This GitHub issue-ErrorVariable 无效生效,因为$ErrorActionPreference = Stop重定向随后会触发 script-收到第一条stderr行后,终止错误


如果您要在收到stderr行时有选择地采取行动

注意:

  • 从本质上讲,在处理行时,您尚不知道该程序最终将报告失败还是成功。

  • 2>&1注意事项也适用于此。

以下示例过滤掉stderr行$ErrorActionPreference = 'Stop'并将行stderr1用红色打印到控制台(仅文本,不像PowerShell错误)。

stderr2

答案 1 :(得分:-1)

我以前在git中遇到过这种情况,并通过使用$LASTEXITCODE来解决。

不确定它是否适用于您的情况,或者因为我没有遇到问题而适用于choco。

# using git in powershell console sends everything to error stream
# this causes red text when it's not an error which is annoying
# 2>&1 redirects all to stdout, then use exit code to 'direct' output

$git_output = Invoke-Expression "& [git pull etc] 2>&1"

# handle output using exitcode
if ($LASTEXITCODE -ne 0) { throw $git_output }
else { Write-Output $git_output }