Powershell无法捕获Perl的标准输出

时间:2018-12-05 14:40:57

标签: powershell perl strawberry-perl

我在powershell中有以下简单脚本(在C:\Users\myusername\Desktop\tests\test.ps1下说)

$counter = 0
while (1) {
    $counter++
    if ($counter % 2) {
        [Console]::Error.WriteLine("($counter) This is an error")
    } else {
        echo "($counter) Some output"
    }
    sleep 1
}

我想以编程方式调用此脚本并将其标准输出和标准错误捕获到文件中(例如C:\Users\myusername\Desktop\test.log)。为此,我编写了以下powershell脚本:

$psi = New-object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.FileName = 'C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe'
$psi.Arguments = @('C:\Users\myusername\Desktop\tests\test.ps1')

$process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi

$logAction = {
    $time = Get-Date -Format o
    Add-Content 'C:\Users\myusername\Desktop\test.log' "($time)[$($Event.MessageData)]: $($Event.SourceArgs.Data)"
}

Register-ObjectEvent -InputObject $process -EventName ErrorDataReceived -Action $logAction -MessageData "STDERR" >$null
Register-ObjectEvent -InputObject $process -EventName OutputDataReceived -Action $logAction -MessageData "STDOUT" >$null

$process.Start() >$null
$process.BeginErrorReadLine() >$null
$process.BeginOutputReadLine() >$null

$process.Id

test.log文件的内容符合预期:

(2018-12-05T15:00:45.7615056+01:00)[STDERR]: (1) This is an error
(2018-12-05T15:00:47.0119743+01:00)[STDOUT]: (2) Some output
(2018-12-05T15:00:47.9497710+01:00)[STDERR]: (3) This is an error
(2018-12-05T15:00:49.8253980+01:00)[STDOUT]: (4) Some output
(2018-12-05T15:00:49.8253980+01:00)[STDERR]: (5) This is an error
(2018-12-05T15:00:51.2008546+01:00)[STDOUT]: (6) Some output
(2018-12-05T15:00:51.8260768+01:00)[STDERR]: (7) This is an error
(2018-12-05T15:01:03.6269252+01:00)[STDERR]:
(2018-12-05T15:01:03.6269252+01:00)[STDOUT]:

但现在出现了有趣的部分。我有以下perl脚本(例如在C:\Users\myusername\Desktop\tests\test.pl下运行),该脚本在Windows中使用Strawberry Perl运行,并且与我的问题中的第一个powershell脚本非常相似:

#!/usr/bin/perl

use strict;
use warnings;

my $counter = 0;

while (1) {
    $counter++;

    if ($counter % 2) {
        print STDERR "($counter) This is an error!\n";
    } else {
        print STDOUT "($counter) Some message\n";
    }

    sleep 1;
}

我还想以编程方式调用此脚本并将其标准输出和标准错误捕获到文件中。为此,我通过将$psi.FileName$psi.Arguments的值更新为以下内容来更改问题中的第二个脚本:

$psi.FileName = 'C:\Strawberry\perl\bin\perl.exe'
$psi.Arguments = @('C:\Users\myusername\Desktop\tests\test.pl')

但是现在test.log文件的内容不是我所期望的

(2018-12-05T14:14:53.9176561+01:00)[STDERR]: (1) This is an error!
(2018-12-05T14:14:55.7926306+01:00)[STDERR]: (3) This is an error!
(2018-12-05T14:14:57.9801317+01:00)[STDERR]: (5) This is an error!
(2018-12-05T14:15:22.2301618+01:00)[STDOUT]:
(2018-12-05T14:15:22.2301618+01:00)[STDERR]:

如您所见,标准输出未捕获。我完全不知道为什么会这样以及如何解决。为什么它不适用于perl但适用于powershell?如何使它与perl一起使用?

我的powershell版本在Windows 10 Pro上是5.1.17134.407。

1 个答案:

答案 0 :(得分:1)

STDERR通常设置为自动冲洗,而STDOUT不是。您的代码希望在编写时收到每条输出行。

尝试在data: {proId: proID}之后将以下两行添加到Perl脚本中

use warnings;