Malcolm Nooning wrote:
Hello,
How can I identify the bundled perl binary from within a pp created
executable? Perl will NOT be installed on the end user's machine.
Specifically, I would like to do something like this:
Win32::Process::Create($ProcessObj,
"full_path_to_the_by now_unwrapped_perl.exe",
"perl.exe bundled_perl_file.pl",
0,
NORMAL_PRIORITY_CLASS,
".")|| die ErrorReport();
I have need for one process to watch another and kill it if there is a
problem. Since I use Tk, which is not thread safe, I cannot use the
Windows fork (Perl 5.8.8 + fork + Tk worked on Windows XP but not on
Windows 2000).
Another solution would be to create a separate pp'd .exe to be executed
as the Win32::Process::Create invoked process. However, the extra time
taken up in the initial unwrapping/unbundling, etcetera, would seem
unpalatable. That is why I am hoping for a scheme wherein I could use
the by-then already unbundled perl.exe.
A quick search reveals that there is no perl.exe anywhere under the
par-malcolm directory. My next question is then ... how could my end
goal be reached?
Thanks
------------------------------
I would like to continue this request for assistance, as I have made
some progress. I think that if I could get this to work it would open
up a lot of areas for PAR/pp.
I would like to have two emails, this one and the next. This first one
outlines how the end goal can be reached by having one .exe invoke
another. Since it works, albeit more slowly than desired, I will just
post this and forget about it.
My next email will show where I am stuck trying to have a faster
implementation.
For those that might get along fine with one exe invoking another, a
"test_minus_a_invoked.exe" can be created, along with an
"invoked.exe", wherein invoked.exe is invoked within
test_minus_a_invoked.exe. The command lines and the reasoning are shown
below. This assumes that the working directory is c:\aaa.
pp -o invoked.exe invoked.pl # Nothing new here
pp -o test_invoked_from_cache.exe -a
"c:/perl/bin/perl.exe;inc/../../perl.exe" -a
"c:/aaa/invoked.exe;invoked.exe" test_invoked_from_cache.pl
Above I am taking C:/perl/bin/perl.exe and putting it into the top level
directory where the perl.dll is normally placed. I do not know if it
is really necessary, but that is what I did.
The business of
"c:/perl/bin/perl.exe;inc/../../perl.exe" is there instead of, say,
"c:/perl/bin/perl.exe;/perl.exe"
because just using "/perl.exe" did not seem to work, so I think I had to
trick pp a little to get it into the upper level cache directory.
The
-a "c:/aaa/invoked.exe;invoked.exe"
puts invoked.exe into .../cache-xxx/inc/invoked.exe.
From here, assuming I have the fully qualified path name to the cache
directory from within test_invoked_from_cache, I can do this within
test_minus_a_invoked.pl
my $fqpn_invoked = File::Spec->catfile( $par_base,
"inc",
"invoked.exe",
);
if (system(" \"$fqpn_invoked\" ")) {
die("100 OUCH\n");
} else {
print("105 Success \n");
}
You may well ask, just how can we know the cache directory? Here is the
way I did it. Does anyone know an easier way?
------------- paste sub
sub find_par_temp_base {
my ($debug) = @_;
#################################################################
# Originally taken from par.pl:_set_par_temp. The lines
# containing $Config{_delim} were replaced by
# File::Spec->catdir(whatever, whatever);
#################################################################
my $path = "";
my $par_temp = "";
my $progname = "";
my $username = "";
my $stmpdir = "";
my $mtime = "";
my $ctx = "";
print("msg210:\n") if $debug;
if ($ENV{PAR_TEMP} and $ENV{PAR_TEMP} =~ /(.+)/) {
$par_temp = $1;
print("msg215: Returning $par_temp\n") if $debug;
return ($par_temp);
}
foreach $path (
(map $ENV{$_}, qw( TMPDIR TEMP TMP )),
qw( C:\\TEMP /tmp . )
) {
next unless $path and -d $path and -w $path;
$username = defined(&Win32::LoginName)
? &Win32::LoginName()
: $ENV{USERNAME} || $ENV{USER} || 'SYSTEM';
$stmpdir = File::Spec->catdir($path, "par-$username");
last;
}
print ("msg270: stmpdir is $stmpdir\n") if $debug;
return ($stmpdir);
}
-------------- end paste sub
and then do:
my $par_base = find_par_temp_base(0);
So there it is. The above was just a proof-of-concept so that one can
have a system command that utilized the already bundled up perl.
But what if you had a parent/child application? The code below also
worked. I pasted it just after the already stated "system" command.
-------------paste this also worked
my $ProcessObj;
my $exitcode = "";
Win32::Process::Create($ProcessObj,
$fqpn_invoked,
"invoked.exe",
0,
NORMAL_PRIORITY_CLASS,
".")|| die ("Phooey:$!:\n");
sleep(2);
print("This is the parent just after waiting for the child\n");
$ProcessObj->Kill($exitcode);
--------------end paste this also worked