Your problem is Win32::Process doesn't fully expose the C function CreateProcess, where you can specify the initial (since the child can switch them out to whatever it wants programatically if it wants) standard handles the child process will get. I modified your script to get cmd.exe's child's PID and changed away from sleep.exe to perl.exe.
use warnings;
use strict;
use Win32::Process;
use Win32::Process 'STILL_ACTIVE';
use Win32::Process::Info qw{WMI};
my $child_pid;
my $real_child_pid;
my $child_proc;
my $cmd = 'perl -e"sleep 20"';
my $debug = 1;
my $exitcode = 1;
my $stdout = 'out.txt';
my $stderr = 'err.txt';
Win32::Process::Create($child_proc, $ENV{COMSPEC}, "/c $cmd > $stdout
+2>$stderr", 0, 0, ".") || print Win32::FormatMessage( Win32::GetLastE
+rror());
$child_pid = $child_proc->GetProcessID();
my $pi = Win32::Process::Info->new();
my ($min_time,$max_time,$kill_time) = (12,15,18);
if($child_pid!=0) {
print "Started child process id $child_pid\n";
my %subs = $pi->Subprocesses($child_pid);
my $real_child_pid = $subs{$child_pid}[0];
print "Real child process id $real_child_pid\n";
#use Data::Dumper;
#print Dumper(\%subs);
my $i=0;
while ( 'true' ) {
$child_proc->Wait(1000);
$i++;
$child_proc->GetExitCode($exitcode);
if ( $exitcode == STILL_ACTIVE ) {
print "loop $i\n";
if($i==$max_time) {
print "max time : this is quite long...\n";
}
if($i==$kill_time) {
print "kill time : kill $child_pid\n";
$child_proc->Kill(-1);
}
}
else {
print "### E = $^E ?=$? ###\n";
print " Process terminated on it's own rc=$exitcode \n";
if($i==$min_time) {
print "min time : command was too short\n";
}
exit $exitcode;
}
}
}
else {
print "Can't start process...\n";
}
What you want to use is
IPC::Run3 or a Perl wrapper around CreateProcess that exposes
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686331%28v=vs.85%29.aspx, specifically "HANDLE hStdOutput" (and according to grep.cpan.me, there is only 1, and its a personal module intended to never be used by the public (
https://metacpan.org/release/DAVEROTH/Win32_AdminMisc_Source_980511), choice 3 is using
Win32::API and calling CreateProcess yourself with that struct.