I am running a command in a Perl script using Win32::Process, and I need to redirect the output of that command to a text file. After doing a bit of research, this is what I am trying:
use Win32::Process;
open (OLDOUT, ">&STDOUT");
open (OLDERR, ">&STDERR");
my $file = "output.txt";
open (STDOUT, ">$file");
open (STDERR, ">&STDOUT");
my $timeout = 1000 * 60; # 60 second timeout
my $proc;
my $exit;
my $exe = "C:/Windows/System32/cmd.exe";
Win32::Process::Create($proc, $exe, "echo hello from process", 1, DETACHED_PROCESS, ".");
$proc->Wait($timeout);
$proc->GetExitCode($exit);
system("echo hello from system"); # To verify that the redirect is working
close (STDOUT);
close (STDERR);
open (STDOUT, ">&OLDOUT");
open (STDERR, ">&OLDERR");
close (OLDOUT);
close (OLDERR);
Unfortunately this is not working. In the output.txt file, I only get "hello from system". Is there a way to accomplish what I want using Win32::Process?
The reason I am using Win32::Process rather than backticks is because my command sometimes crashes, and I need to provide a timeout in order to kill it if neccessary. The ->Wait() function of Win32::Process allows me to do this.
I would rather have a solution using Win32::Process, as I am limited to which modules I have access to. However, if this really cannot be done, I would welcome an example solution using some other module.
Thank you.
You are specifying DETACHED_PROCESS
when you start the process. The effect of this is the following:
DETACHED_PROCESS
0x00000008
For console processes, the new process does not inherit its parent's console (the default).
The reason passing "echo hello from process"
as the command line to Win32::Process
doesn't work is because echo
is a cmd.exe
builtin. You need to instead use the command line 'cmd /c "echo hello from process"'
as shown below:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Which qw(which);
use Win32;
use Win32::Process;
open OLDOUT, ">&STDOUT";
open OLDERR, ">&STDERR";
my $file = 'output.txt';
open STDOUT, ">$file";
open STDERR, ">&STDOUT";
my $timeout = 15 * 1_000;
my ($proc, $exit);
my $exe = which 'cmd.exe';
Win32::Process::Create($proc, $exe, 'cmd /c "echo hello from spawned process"', 1, 0, '.');
$proc->Wait($timeout);
$proc->GetExitCode($exit);
print "Doing work ...\n"; sleep 3;
print "Spawned process exited with $exit\n";
close STDERR;
close STDOUT;
open STDERR, ">&OLDERR";
open STDOUT, ">&OLDOUT";
close OLDERR;
close OLDOUT;
Contents of output.txt
:
$ perl main.pl
$ type output.txt
hello from spawned process
Doing work ...
Spawned process exited with 0