简体   繁体   English

Powershell 不捕获 perl 的标准输出

[英]Powershell not capturing perl's standard output

I have the following simple script in powershell (say under C:\\Users\\myusername\\Desktop\\tests\\test.ps1 )我在 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
}

I want to programmatically invoke this script and capture its standard output and standard error into a file (say C:\\Users\\myusername\\Desktop\\test.log ).我想以编程方式调用此脚本并将其标准输出和标准错误捕获到文件中(例如C:\\Users\\myusername\\Desktop\\test.log )。 For that I wrote the following powershell script:为此,我编写了以下 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

The content of the test.log file is as expected: 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]:

But now comes the interesting part.但现在是有趣的部分。 I have the following perl script (say under C:\\Users\\myusername\\Desktop\\tests\\test.pl ) which I run in Windows using Strawberry Perl , and which pretty much resembles the first powershell script in my question:我有以下 perl 脚本(比如在C:\\Users\\myusername\\Desktop\\tests\\test.pl ),我使用Strawberry Perl在 Windows 中运行它,它非常类似于我问题中的第一个 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;
}

I also want to programmatically invoke this script and capture its standard output and standard error into a file.我还想以编程方式调用此脚本并将其标准输出和标准错误捕获到文件中。 For that I change the second script in my question by updating the $psi.FileName and $psi.Arguments values to:为此,我通过将$psi.FileName$psi.Arguments值更新为:

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

But now the content of the test.log file is not what I expected但是现在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]:

As you can see the standard output is not getting captured.正如您所看到的,标准输出没有被捕获。 I have absolutely no idea why is this happening and how can I solve it.我完全不知道为什么会这样,我该如何解决。 Why is it not working for perl but it does for powershell?为什么它不适用于 perl 但它适用于 powershell? How can I get it to work with perl?我怎样才能让它与 perl 一起工作?

My powershell version is 5.1.17134.407 on a Windows 10 Pro.我在 Windows 10 专业版上的 powershell 版本是 5.1.17134.407。

STDERR is usually set up for auto-flush, STDOUT is not. STDERR 通常设置为自动刷新,而 STDOUT 则不是。 Your code expects to receive every output line as it is written.您的代码期望在编写时接收每个输出行。

Try adding the following 2 lines to your Perl script after use warnings;尝试在use warnings;后将以下两行添加到您的 Perl 脚本中use warnings;

use IO::Handle;
STDOUT->autoflush(1);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM