windows 捕获程序 stdout 和 stderr 以分隔变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24222088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 11:37:20  来源:igfitidea点击:

Capture program stdout and stderr to separate variables

windowspowershellcommand-linestdoutstderr

提问by dusz

Is it possible to redirect stdout from an external program to a variable and stderr from external programs to another variable in one run?

是否可以在一次运行中将 stdout 从外部程序重定向到变量,并将 stderr 从外部程序重定向到另一个变量?

For example:

例如:

$global:ERRORS = @();
$global:PROGERR = @();

function test() {
    # Can we redirect errors to $PROGERR here, leaving stdout for $OUTPUT?
    $OUTPUT = (& myprogram.exe 'argv[0]', 'argv[1]');

    if ( $OUTPUT | select-string -Pattern "foo" ) {
        # do stuff
    } else {
        $global:ERRORS += "test(): oh noes! 'foo' missing!";
    }
}

test;
if ( @($global:ERRORS).length -gt 0 ) {
    Write-Host "Script specific error occurred";
    foreach ( $err in $global:ERRORS ) {
        $host.ui.WriteErrorLine("err: $err");
    }
} else {
    Write-Host "Script ran fine!";
}

if ( @($global:PROGERR).length -gt 0 ) {
    # do stuff
} else {
    Write-Host "External program ran fine!";
}

A dull example however I am wondering if that is possible?

一个沉闷的例子但是我想知道这是否可能?

采纳答案by Keith Hill

The easiest way to do this is to use a file for the stderr output, e.g.:

最简单的方法是为 stderr 输出使用一个文件,例如:

$output = & myprogram.exe 'argv[0]', 'argv[1]' 2>stderr.txt
$err = get-content stderr.txt
if ($LastExitCode -ne 0) { ... handle error ... }

I would also use $LastExitCode to check for errors from native console EXE files.

我还将使用 $LastExitCode 检查本机控制台 EXE 文件中的错误。

回答by Aaron Schultz

One option is to combine the output of stdout and stderr into a single stream, then filter.

一种选择是将 stdout 和 stderr 的输出组合成一个流,然后进行过滤。

Data from stdout will be strings, while stderr produces System.Management.Automation.ErrorRecord objects.

来自 stdout 的数据将是字符串,而 stderr 生成 System.Management.Automation.ErrorRecord 对象。

$allOutput = & myprogram.exe 2>&1
$stderr = $allOutput | ?{ $_ -is [System.Management.Automation.ErrorRecord] }
$stdout = $allOutput | ?{ $_ -isnot [System.Management.Automation.ErrorRecord] }

回答by AckSynFool

You should be using Start-Process with -RedirectStandardError -RedirectStandardOutput options. This other posthas a great example of how to do this (sampled from that post below):

您应该使用带有 -RedirectStandardError -RedirectStandardOutput 选项的 Start-Process。这个其他职位有如何做到这一点(从下后取样)一个很好的例子:

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "ping.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "localhost"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode

回答by James Eby

This is also an alternative that I have used to redirect stdout and stderr of a command line while still showing the output during PowerShell execution:

这也是我用来重定向命令行的 stdout 和 stderr 的替代方法,同时在 PowerShell 执行期间仍然显示输出:

$command = "myexecutable.exe my command line params"

Invoke-Expression $command -OutVariable output -ErrorVariable errors
Write-Host "STDOUT"
Write-Host $output
Write-Host "STDERR"
Write-Host $errors

It is just another possibility to supplement what was already given.

这只是补充已经给予的另一种可能性。

Keep in mind this may not always work depending upon how the script is invoked. I have had problems with -OutVariable and -ErrorVariable when invoked from a standard command line rather than a PowerShell command line like this:

请记住,这可能并不总是有效,具体取决于脚本的调用方式。当从标准命令行而不是像这样的 PowerShell 命令行调用时,我遇到了 -OutVariable 和 -ErrorVariable 的问题:

PowerShell -File ".\FileName.ps1"

An alternative that seems to work under most circumstances is this:

在大多数情况下似乎有效的替代方法是:

$stdOutAndError = Invoke-Expression "$command 2>&1"

Unfortunately, you will lose output to the command line during execution of the script and would have to Write-Host $stdOutAndErrorafter the command returns to make it "a part of the record" (like a part of a Jenkins batch file run). And unfortunately it doesn't separate stdout and stderr.

不幸的是,您将在脚本执行期间丢失命令行的输出,并且必须Write-Host $stdOutAndError在命令返回后才能使其成为“记录的一部分”(就像 Jenkins 批处理文件运行的一部分)。不幸的是,它没有将 stdout 和 stderr 分开。