use strict;
use warnings;
sub read_file_contents
{
my $fname = shift;
open( my $fh, '<', $fname ) or die "error: open '$fname': $!\n";
local $/ = undef; # slurp mode
my $s = <$fh>;
close($fh);
return $s;
}
# Run a Windows executable synchronously.
# Return a three element list:
# the return code; the stdout of the command; and the stderr of the command.
# Die if something goes wrong.
sub run_cmd_sync
{
my ( $exe, $cmd, $workdir ) = @_;
defined($workdir) or $workdir = ".";
require Win32::Process;
my $tmpout = "klink-out-$$.tmp";
my $tmperr = "klink-err-$$.tmp";
-f $exe or die "error: file '$exe' not found";
local *SAVOUT;
local *SAVERR;
# save original stdout and stderr
open( SAVOUT, ">&STDOUT" ) or die "error: open SAVOUT: $!";
open( SAVERR, ">&STDERR" ) or die "error: open SAVERR: $!";
open( STDOUT, '>', $tmpout ) or die "error: can't redirect stdout";
open( STDERR, '>', $tmperr ) or die "error: can't redirect stderr";
Win32::Process::Create(
my $hProc, # process object
$exe, # executable
$cmd, # command line
1, # inherit handles
Win32::Process::NORMAL_PRIORITY_CLASS(),
$workdir # working dir
) or die "error: Win32::Process::Create: $^E ($!)";
my $pid = $hProc->GetProcessID();
# parent continues (redirect back to original) ...
close(STDOUT);
close(STDERR);
open( STDOUT, ">&SAVOUT" ) or die "error: open SAVOUT: $!";
open( STDERR, ">&SAVERR" ) or die "error: open SAVERR: $!";
print "started exe:$exe (cmd:$cmd) ok, pid=$pid.\n";
my $rc = 0;
$hProc->Wait( Win32::Process::INFINITE() ) or die "error: Wait: $^E ($!)";
$hProc->GetExitCode($rc) or die "error: GetExitCode: $^E ($!)";
my $outstr = read_file_contents($tmpout);
my $errstr = read_file_contents($tmperr);
unlink($tmpout) or die "error: unlink '$tmpout': $!\n";
unlink($tmperr) or die "error: unlink '$tmperr': $!\n";
return ( $rc, $outstr, $errstr );
}
my ( $rc, $outstr, $errstr ) = run_cmd_sync(
$^X,
'perl -e "print q{hello stdout}; print STDERR q{hello stderr}"',
'.'
);
print "rc='$rc'\n";
print "stdout='$outstr'\n";
print "stderr='$errstr'\n";
####
started exe:C:\Strawberry\perl\bin\perl.exe (cmd:perl -e "print q{hello stdout}; print STDERR q{hello stderr}") ok, pid=3132.
rc='0'
stdout='hello stdout'
stderr='hello stderr'
##
##
# Test program tt1.pl
use strict;
use warnings;
# Run a command without invoking the command shell.
# exe is the command name
# @_ contains the command line arguments (including argv[0])
sub run_cmd_noshell
{
my $exe = shift;
print "run '$exe' with args:\n '@_'\n";
system { $exe } @_;
my $rc = $? >> 8;
$rc == 0 or warn "error: exit code=$rc\n";
}
run_cmd_noshell($^X, $^X, '-le', 'print q{hello one};');
run_cmd_noshell($^X, 'perl', '-le', 'print q{hello two}; exit 42;');
##
##
run 'C:\Strawberry\perl\bin\perl.exe' with args:
'C:\Strawberry\perl\bin\perl.exe -le print q{hello one};'
hello one
run 'C:\Strawberry\perl\bin\perl.exe' with args:
'perl -le print q{hello two}; exit 42;'
hello two
error: exit code=42