Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Making pl2bat.pl more robust

25 views
Skip to first unread message

Jan Dubois

unread,
Mar 25, 2008, 8:05:48 PM3/25/08
to The Perl5 Porters Mailing List, David Golden
I'm trying to make pl2bat a little more robust. It currently has the
annoying habit of executing e.g. a "foo" file found anywhere on the PATH
if I call the foo.bat simply as "foo", but will execute the content of
"foo.bat" (also located via PATH) if it can't find "foo" itself. This
generally will lead to weird results if for example you have a "foo" in
your current directory and it is not the one you expected to execute.

pl2bat generated batch files also look up perl.exe on the PATH instead
of loading it from the same tree as the batch file itself (when
applicable).

I've tried to come up with some cmd.exe code that will try to determine
the full pathname of the batch file itself (which turned out to be
harder than I thought it would be because the whole %~ full path
expansion doesn't work correctly if %0 was given as a quoted string).

The script then tries to locate a "perl.exe" in the same directory (for
all scripts installed into perl/bin). Otherwise it checks if the batch
file is in a site/bin directory and tries to use ../../bin/perl.exe if
it exists before falling back to a PATH search.

Here is a little sample script that implements this logic. I would
appreciate if other Windows users could try it out to see if there are
any cases it doesn't cover correctly:

------------------------------------------------------------------------
@echo off
setlocal enableextensions

set _BAT_=%~f0
if exist "%_BAT_%" goto findperl

set _BAT_=%_BAT_%.bat
if exist "%_BAT_%" goto findperl

set _BAT_=%~$PATH:0
if exist "%_BAT_%" goto findperl

for %%F in ("%~0.bat") do set _BAT_=%%~$PATH:F
if exist "%_BAT_%" goto findperl

echo *** Cannot find full path to %0 ***
goto :eof

:findperl
echo BAT: %_BAT_%

for %%F in ("%_BAT_%") do set _PERL_=%%~dpFperl.exe
if exist "%_PERL_%" goto runperl
if /i "%_PERL_:~-18%" equ "\site\bin\perl.exe" (
set _PERL_=%_PERL_:~0,-18%\bin\perl.exe
)
if not exist "%_PERL_%" set _PERL_=perl

:runperl
echo PERL: %_PERL_%
"%_PERL_%" -we "print '$^X: ', $^X"
goto :eof
------------------------------------------------------------------------

I think I tried most combinations of the following, but maybe I'm
forgetting about some other special cases:

* put the script into a directory with spaces in the name
* use a filename containing spaces for the script
* put the script into the Perl/bin directory
* put the script into the Perl/site/bin directory
* invoke the script by name, with and without .bat extension
* put quotes around the script name when you invoke it
* use absolute and relative path names to invoke it
* use shortcuts in the Start menu to run the script

As far as I can tell it is now always finding the correct absolute
pathname for the batch file itself. Let me know if you can come up with
a scenario that leads to the "*** Cannot find full path" error message.

I'll integrate this code into pl2bat.pl (and runperl.pl) if we can agree
that it is more robust than the current logic (note that the current
code already uses %*, so it already assumes that cmd.exe extensions are
available and enabled).

Oops, forgot to mention: all this code is for the Windows_NT branch
only; I don't think there is anything we can do for Win9X.

Cheers,
-Jan

PS: Here are some notes I wrote while writing the code to determine
_BAT_ above:

There are 6 different scenarios:

1) unqoted command name, with or without path
- %~f0 expansion works

2) quoted command name, includes relative or absolute path
- %~f0 expansion works

3) quoted command name, .bat file extension specified, in current directory
- %~f0 expansion accidentally produces the correct result
- must check manually because %~$PATH:0 does not find it

4) quoted command name, no file extension, in current directory
- %~f0 expansion is missing the .bat file extension

5) quoted command name, .bat file extension specified, on PATH
- %~f0 wrongly contains current directory name followed by command name
- %~$PATH:0 finds the batch file on the PATH

6) quoted command name, no file extension, on PATH
- %~f0 wrongly contains current directory name followed by command name
- must look for "%~0.bat" on PATH
- must be tested after 4 so that foo.bat finds foo.bat in preferance of
foo.bat.bat if both files exist somewhere on the PATH (this is not
not completely correct, but close enough).

The whole "look up in $VAR path list" feature seems very simplistic; it
doesn't implement the usual PATH search logic used by CreateProcess() and/or
ShellExecuteEx().


Jan Dubois

unread,
Mar 25, 2008, 8:13:42 PM3/25/08
to The Perl5 Porters Mailing List, David Golden
On Tue, 25 Mar 2008, Jan Dubois wrote:
>
> 3) quoted command name, .bat file extension specified, in current directory
> - %~f0 expansion accidentally produces the correct result
> - must check manually because %~$PATH:0 does not find it

The "must check manually because %~$PATH:0 does not find it" comment actually
belongs to case 4) below:

> 4) quoted command name, no file extension, in current directory
> - %~f0 expansion is missing the .bat file extension

Sorry about the confusion.

Cheers,
-Jan


Reini Urban

unread,
Mar 26, 2008, 5:28:13 AM3/26/08
to pp
2008/3/26, Jan Dubois:

> Oops, forgot to mention: all this code is for the Windows_NT branch
> only; I don't think there is anything we can do for Win9X.

bash + cygwin:
URBANR ~/Perl/B-C/script
$ ~/Perl/pl2bat.bat perlcc
BAT: d:\Data\URBANR\My Documents\Perl\pl2bat.bat
PERL: perl
$^X: /usr/bin/perl.exe

So even on weird cygwin paths within a bash it works.

Now on some spaced path in cmd, but with cygwin perl in path before.
> pl2bat.bat perlcc
BAT: C:\Program Files\Java\jre1.6.0_03\bin\pl2bat.bat
PERL: perl
$^X: /usr/bin/perl.exe

Hmm, /usr/bin/perl.exe is not that good, but one can only it expect it from
such a wrong path
Now fix it by prepending the windows perl path.
> PATH=c:\PERL\bin;C:\Program Files\Java\jre1.6.0_03\bin; ...

>pl2bat.bat perlcc

>

Not good.
> perl -v
This is perl, v5.8.8 built for MSWin32-x86-multi-thread
...

H:\Perl\B-C\script> h:\perl\pl2bat.bat perlcc
BAT: h:\Perl\pl2bat.bat
PERL: perl
$^X: c:\Perl\bin\perl.exe

With explicit path to pl2bat.bat is works. Searching in a spaced path not.
--
Reini Urban
http://phpwiki.org/ http://murbreak.at/

0 new messages