如何将所有输出流写入 PowerShell 中的变量?

How do you write all output streams to a variable in PowerShell?

在 PowerShell 中,我无法将错误流输出写入变量。

运行 不将输出保存到变量的命令将导致任何流的输出可见,但是唉,我需要将输出写入变量。

& terraform $action $arguments

最初我开始使用它。但是,只有成功流被写入变量(如预期的那样)。

$res = & terraform $action $arguments

所以我参考了docs for about_Redirection,但问题是,当我将错误流(或所有流)重定向到成功流时,我仍然只看到写入变量的成功流。我做了几次尝试,都失败了。

$res = & terraform $action $arguments 2>&1
$res = & terraform $action $arguments *>&1
$res = & terraform $action $arguments *>&1 | ForEach-Object { $_.ToString() }

但是,如果我将错误流重定向到一个文件,那么该流将按预期写入。

$res = & terraform $action $arguments 2>> terraform-errors.log

如何将所有流的输出写入变量?

我终于找到了答案,问题是由于设置$ErrorActionPreference = Stop

发生终止时,脚本在重定向输出之前被终止。要解决这个问题,必须更改错误操作首选项,然后可以使用 Invoke-Expression 和一些 common parameters.

将错误和输出发送到变量
$ErrorActionPreference = "SilentlyContinue"
Invoke-Expression "& terraform $action $arguments 2>&1" -ErrorVariable terraformError -OutVariable terraformState | Out-Null
$ErrorActionPreference = "Stop"

### Check if there was an error.
if ($terraformError) {
    throw $terraformError
}

为什么不使用 -ErrorAction 来更改错误操作首选项?

遗憾的是 -ErrorAction 仅适用于非终止错误。因为脚本的错误操作首选项是 Stop,这意味着 Invoke-Expression 命令将始终触发终止错误,而不管 -ErrorAction 公共参数的值如何。

要解决此问题,必须在 Invoke-Expression 命令为 运行 之前更改错误操作首选项,然后在完成后更改回来。

为什么输出通过管道传输到 Out-Null

尽管将错误和输出保存到变量,但输出也将流式传输到控制台,而无需通过管道将其传输到 Out-Null

显然这是可选的,因为在某些情况下可能 acceptable/expected 输出也会流式传输到控制台。