m.nooning wrote:
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





--------------------------------------------
>so that one can have a system command that utilized the already bundled up perl. I was getting a little ahead of myself there. The prior email was working with pp'd exe files, one via "system", and the other via Win32::Process::Create.

Now I would like to reach the goal of using a system command that utilized the already bundled up perl. If that could be done, then coming up with a parent/child scheme with Win32::Process::Create would easily follow.

I am really just looking for advice about things I might be able to try.

I intend here to present something that, seems to me, should have worked. I intend to show some code snippets to bring out the reasoning, and then give the pp command, then show the errant results, and then show the actual proof-of-concept test files used.

As I stated, it looks (to me) like it should have worked. Again, if this problem can be solved I think it will open up par/pp to a new class of applications. Namely, to those applications wherein a parent needs to create and watch a child while at the same time using a non-thread safe gui tool such as Tk.

Okay, here we go.

In this case, the buildup of the system command would look something like this:

---------paste proposed parent code
my $par_base = find_par_temp_base(0); # As before

# My pp command line will put the perl.exe here:
my $fqpn_perl = File::Spec->catfile($par_base,  "perl.exe");

# My pp command line will put the child .pl file here:
my $fqpn_invoked = File::Spec->catfile( $par_base,
                                        "inc",
                                        "invoked_as_pl.pl",
                                      );

# The child process will need all the libraries of the already
# unbundled perl so I will have to give it the parent's @INC path.
# The invoked_as_pl.pl file will get the inc path in $ARGV[0];
my $inc = join(" ", @INC);

if (system(" \"$fqpn_perl\" \"$fqpn_invoked\" \" . $inc . \" ")) {
------------end paste parent code

The invocation command would look like this:

pp -o test_minus_a_invoked.exe -a "c:/perl/bin/perl.exe;inc/../../perl.exe" -a "c:/aaa/invoked_as_pl.pl;invoked_as_pl.pl" test_minus_a_invoked.pl

Unfortunately, it does not work. I get an error indicating that Tk.pm (used in invoked_as_pl.pl) cannot be found, as shown below. But the Tk.pm file certainly is in the path. So ... what is wrong?

-------------paste results
C:\aaa>test_minus_a_invoked.exe
Parental path is
C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc\lib C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc CODE(0xef4644) CODE(0xef477c) Child says ARGV 0 is C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc\lib C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc
CODE(0xef4644) CODE(0xef477c)
Can't locate Tk.pm in @INC (@INC contains: . C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc\lib C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a3 0007fccb5d9d6748757\inc CODE(0xef4644) CODE(0xef477c) ) at C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc\invoked_as_pl.pl line 13. BEGIN failed--compilation aborted at C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc\invoked_as_pl.pl line 13.
100 Cannot
----------------end paste results

--------------paste location of Tk.pm
Directory of C:\DOCUME~1\malcolm\LOCALS~1\Temp\par-malcolm\cache-844032a64d7cff289f1a30007fccb5d9d6748757\inc\lib
01/22/2007  07:22 PM            19,053 Tk.pm
---------------end paste location of Tk.pm

As you can see above, Tk.pm is in the path that the invoked_as_pl.pl file knows about.
Here is the test_minus_a_invoked.pl

--------------paste test_minus_a_invoked.pl
#!/usr/bin/perl -w
#File test_minus_a_invoked.pl
# Works when doing this:
# pp -o test_minus_a_invoked.exe -a            \
#    "c:/perl/bin/perl.exe;inc/../../perl.exe"       \
# -a "c:/aaa/invoked_as_pl.pl;invoked_as_pl.pl" test_minus_a_invoked.pl
#
#########################################################################
use PAR;
use File::Spec;
use Tk;
use Cwd;
use Win32::Process;
use Win32;

####################
sub okay_response {
  my ($we_top) = @_;
  $we_top->destroy;
}

###################
sub pop_up_a_message {
  my ( $message, ) = @_;
  my $okay_button;

  my $we_top = new MainWindow;

  $we_top->Label
       (
          -text => $message . "\n",
          -justify => 'left',
       )->pack(-padx =>10);

  #.....................................................................
  $okay_button =
      $we_top->Button(  -text => "Okay",
                        -command => [  \&okay_response,
                                       $we_top,
                                    ]
                      )->pack(-ipadx =>10);
  #.....................................................................

  #########
  MainLoop;
  #########

}

###################

########################################################################
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);
}

########################################################################


pop_up_a_message ("Hello from parent\n");

my $par_base = find_par_temp_base(0);

my $fqpn_perl = File::Spec->catfile($par_base,  "perl.exe");
my $fqpn_invoked = File::Spec->catfile( $par_base,
                                        "inc",
                                        "invoked_as_pl.pl",
                                      );

my $inc = join(" ", @INC);
print ("Parental path is \n");
print ("@INC\n");

if (system(" \"$fqpn_perl\" \"$fqpn_invoked\" \" $inc  \" ")) {
  die("100 Cannot\n");
} else {
print("105 Success with system \"$fqpn_perl\" \"$fqpn_invoked\" . \" . $inc . \"\n");
}

--------------end paste test_minus_a_invoked.pl

and, lastly,

----------------paste invoked_as_pl.pl
#File: invoked_as_pl.pl

BEGIN {
  push (@INC, ($ARGV[0]));
  print "Child says ARGV 0 is $ARGV[0]\n";
}

if (@ARGV == 0 ) {
  print("520: You forgot the parameter for invoked_as_pl.pl\n");
  exit(1);
}

use Tk;

####################
sub okay_response {
  my ($we_top) = @_;
  $we_top->destroy;
}

###################
sub pop_up_a_message {
  my ( $message, ) = @_;
  my $okay_button;

  my $we_top = new MainWindow;

  $we_top->Label
       (
          -text => $message . "\n",
          -justify => 'left',
       )->pack(-padx =>10);

  #.....................................................................
  $okay_button =
      $we_top->Button(  -text => "Okay",
                        -command => [  \&okay_response,
                                       $we_top,
                                    ]
                      )->pack(-ipadx =>10);
  #.....................................................................

  #########
  MainLoop;
  #########

}

###################

pop_up_a_message ("Hello from child\n");
print "Hello from invoked_as_pl.pl\n";
exit (0);

---------------end paste invoked_as_pl.pl




Reply via email to