如何使用Perl启动Win32程序并将其输出重定向到stdout?

时间:2009-12-14 12:04:10

标签: perl winapi stdout

我有一个跨平台的Perl程序,它在win上启动win32 windows程序,在mac上启动macosx appliaction。

我使用system(),它在mac上生成被调用程序的stdout,写在Perl程序的stdout中,这就是我想要的。

在Windows上,似乎没有办法让stdout成为Windows程序。所以作为替代方案,我让程序写入日志文件而不是,我希望Perl从日志文件中读取(因为它被写入,被调用的程序可以运行一个小时),并将其重定向回Perl的标准输出,因此Win和Mac上的体验是一样的。

有人知道如何在Perl中实际执行此操作吗?我在想:

  • 分叉过程
  • File ::尾随日志文件,在数据进入
  • 时写入stdout
  • 以某种方式弄清楚程序何时实际运行完毕。

我可能会弄清楚#1和#2,但还不知道如何解决#3。

6 个答案:

答案 0 :(得分:4)

以下是否符合您的初衷:stdout win32计划也是stdout的{​​{1}}(或者我是否误解了您原来的问题)?

perl

Perl程序捕获// Win32 console application printing to stdout #include <stdio.h> int main(int argc, char* argv[]) { int idx; for (idx=0; idx < 10; idx++) { printf("Hello World!\n"); fflush(stdout); } return 0; } 的Windows程序并重定向到stdout

stdout

答案 1 :(得分:2)

如果您需要捕获程序打印到STDOUT的输出,为什么不简单地使用反引号代替system()

my $stdout = `program_name`;
if ( $? ) {
    print "Child process had an error";
}

答案 2 :(得分:2)

IPC::Run3允许你为stdin提供东西并捕获stdout和stderr。

答案 3 :(得分:0)

您是否阅读过system的文档? system不允许您捕获STDOUTqx确实如此。

另一方面,看起来你真的不想捕获STDOUT。您似乎希望程序的输出显示在与Perl程序相同的终端窗口中。如果您在Windows上调用的程序确实将其输出打印到STDOUT,并且如果您在cmd窗口中运行Perl程序,那么这将自然发生。

答案 4 :(得分:0)

捕获fork调用的返回值以获取子进程ID。

my $pid = fork();
if ($pid == 0) { # child
    system("command > logfile");
    exit 0;
}
# else parent
do {
    # ... apply File::Tail to logfile, print new output ... 
while (process_is_active($pid));

然后有很多方法可以判断孩子什么时候结束。这是两个:

# 1. kill 0, $pid
sub process_is_active {
    my ($pid) = @_;
    return kill 0, $pid;  # returns "number of processes successfully signalled"
}

有些系统比其他系统更好地实施kill 0,...

# 2. non-blocking waitpid 
sub process_is_active {
    use POSIX ':sys_wait_h';
    my ($pid) = @_;
    my $waitpid = waitpid $pid, WNOHANG;
    return $waitpid == $pid;
}

第二个解决方案只能运行一次 - 在waitpid检测到该流程完成并收到该流程后,如果您在该流程上再次调用它,它将返回-1

答案 5 :(得分:0)

不确定“get stdout”是什么意思,但是当从Windows命令行使用perl.exe运行时,这正确地将“foo”打印到标准输出:

perl -e "system 'echo foo'"

所以我认为只要你在命令窗口中运行Perl,并且在调用system之前不要试图弄乱任何stdout文件句柄它应该有效。