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

问题描述 投票:3回答:2

我知道ErrorAction的说法,也$ErrorActionPreference$Error$

上下文

我想解决的问题是运行一个外部命令(例如巧克力或GIT)提示错误应该被警告,甚至没有警告,在我的任务范围内,至少在。

因为他们的退出代码的PowerShell的认为,作为误差在任何意义上,例如写出红输出等,这是不是在我的任务的上下文可取的。

我可以抑制与-ErrorAction2> $null这些命令的错误输出,但我有完全消失的任何错误的特定命令的这样一种不好的预感。

我想只有忽略称为“在这种情况下不是我的问题”类型的错误。

有没有什么办法来处理一个命令的错误忽略一些特定的,但通常对待所有其他错误条件?

powershell error-handling powershell-v3.0
2个回答
3
投票
  • 在常规控制台窗口中,在PowerShell中V3及以上,标准错误打印出的线条,就像标准输出线。 这是可取的,因为标准错误被许多程序并不只是报告真正的错误,但是任何不是数据,如状态信息。 标准错误线(除非重定向 - 见下文)打印直通过控制台(而标准输出线被发送到PowerShell的成功输出流中,在那里他们可以在一个变量中被收集,通过管道发送,或者与> / >>重定向)。
  • 令人遗憾的是,PowerShell ISE中,即使是在V5.1中,可以打印标准错误线为红色,在相同的格式PowerShell的错误。 Visual Studio Code与PowerShell的扩展名不存在这个问题,值得迁移到一般,因为未来所有的开发工作将集中在那里,因为它也适用与跨平台PowerShell核心版本。
  • 乖巧的控制台应用程序只使用他们的退出代码信号成功(退出代码0)与失败(任何非零的退出代码)。 PowerShell的保存在其自动$LASTEXITCODE变量最近调用控制台应用程序的退出代码。
  • 作为旁白: 常用参数-ErrorAction-ErrorVariable不能与外部程序使用。 类似地,优选的可变$ErrorActionPreference没有效果(除了偶然,由于this bug,如PowerShell的V5.1 / PowerShell核心6.2.0-preview.4的)。 try / catch不能用来检测和处理外部程序的失败。 对于PowerShell的复杂的错误处理规则的全面概述,请参阅this GitHub docs issue

注意:我使用在下面的实施例,其产生1行标准输出和1线stderr输出的下面的外部命令(请注意,重定向>&2cmd处理,不PowerShell中,因为它是'...'内;它是用于产生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 = @() # 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"
}
  • 注意2>&1重定向,它指示PowerShell来发送通过管道STDERR线(流2,错误流)(流1,成功流)也是如此。
  • Where-Object块,$_ -is [System.Management.Automation.ErrorRecord]用于识别stderr的线,因为PowerShell的包装这样的线路在该类型的实例。

或者,你可以收集在一个临时文件(2>/path/to/tmpfile)stderr输出,阅读其内容,并删除它。

This GitHub issue提出引入一个变量收集重定向stderr输出的选项,类似于你如何问cmdlet来收集通过公共参数变量错误 -ErrorVariable

有两点需要说明:

  • 固有地,通过后仅打印stderr的线,相对于标准输出输出的特定上下文可能会丢失。
  • 由于bug as of Windows PowerShell v5.1 / PowerShell Core 6.2.0$ErrorActionPreference = Stop不能生效,因为2>&1重定向然后尽快的第一标准错误行收到触发脚本终止错误。

如果你想选择在stderr上线充当他们正在接受:

注意:

  • 本质上,当你正在处理的行,你就还不知道程序是否会最终报告的成功与否。
  • $ErrorActionPreference = 'Stop'警告这里也适用。

下面的示例筛选出标准错误线stderr1并打印线stderr2到控制台以红色(纯文本,而不是像一个PowerShell的错误)。

$stdOut = cmd /c 'echo stdout & echo stderr1 >&2 & echo stderr2 >&2' 2>&1 |
  ForEach-Object { 
    if ($_ -is [System.Management.Automation.ErrorRecord]) { # stderr line
      $stdErrLine = $_.ToString()
      switch -regex ($stdErrLine) {
        'stderr1' { break } # ignore, if line contains 'stderr1'
        default   { Write-Host -ForegroundColor Red $stdErrLine }
      }
    } else { # stdout line
      $_ # pass through
    }
  }

# Handle error.
if ($LASTEXITCODE -ne 0) { Throw "cmd failed." }

-1
投票

我遇到这种情况与以前的git,利用$LASTEXITCODE围绕它的工作。

不知道是否是适用于您的情况,或如巧克力,我没有与它的问题。

# 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 }
© www.soinside.com 2019 - 2024. All rights reserved.