我知道ErrorAction
的说法,也$ErrorActionPreference
,$Error
和$
。
上下文
我想解决的问题是运行一个外部命令(例如巧克力或GIT)提示错误应该被警告,甚至没有警告,在我的任务范围内,至少在。
因为他们的退出代码的PowerShell的认为,作为误差在任何意义上,例如写出红输出等,这是不是在我的任务的上下文可取的。
我可以抑制与-ErrorAction
或2> $null
这些命令的错误输出,但我有完全消失的任何错误的特定命令的这样一种不好的预感。
我想只有忽略称为“在这种情况下不是我的问题”类型的错误。
题
有没有什么办法来处理一个命令的错误忽略一些特定的,但通常对待所有其他错误条件?
>
/ >>
重定向)。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输出的下面的外部命令(请注意,重定向>&2
由cmd
处理,不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
。
有两点需要说明:
$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." }
我遇到这种情况与以前的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 }