How do I make Perl scripts recognize command-line parameters in the Win32 cmd console?
Asked Answered
I

9

6

When I invoke my Perl scripts in the Windows environment without invoking perl first, the parameters are not passed to my script.

For example,

C:\my-perl-scripts\foo.pl bar

invokes foo.pl, but it doesn't recognize bar as a parameter (@ARGV is empty). However,

perl C:\my-perl-scripts\foo.pl bar

works as expected.

Is this a configuration issue?

Ideally, I'd like to be able to distribute some Perl scripts, have the user add C:\my-perl-scripts\ to the path and then just be able to invoke foo.pl from anywhere while running cmd.

If they have to specify perl first, then they'll always have to give a complete path.

To show that the assoc and ftype are correct on my system, I executed the following commands.

assoc .pl

Output:

.pl=Perl

And

ftype Perl

Output:

Perl="C:\Perl\bin\perl.exe" "%1" %*

And:

more t.pl

Output:

print "'$_'\n" for @ARGV;

And:

t a b
    perl t.pl a b

Output:

'a'
'b'

And (no output):

t.pl a b

I included both the output of t and t.pl to show it's not a %PATHEXT% problem. Both outputted nothing as originally described whereas invoking perl first gave the expected response.

The problem appears to be on my vista business box. On my Windows XP Pro box, it works as expected. Both have ActivePerl 5.8.9. I have another Windows Vista Home box that I have not yet tried yet.

I found the answer (posted below). I found it by running a registry cleaner, removing the Perl installation, running the registry cleaner again. On the second cleaning, only one invalid entry remained—the one that was causing the problem (probably left over from a previous installation).

Incised answered 8/11, 2009 at 2:47 Comment(1)
Related: How can I pass command-line arguments to a Perl program?Panama
I
19

I found out what the problem was. Although the ftype and the assoc values were set as suggested, the actual behavior on my system seems to be determined by the registry key

HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command

It should have a (Default) string value of "C:\Perl\bin\perl.exe" "%1" %*

When I found this entry, it was set to "C:\Perl\bin\perl.exe" "%1". Changing it immediately fixed the problem.

Why was it set that way in the first place? I don't know. Maybe from a previous installation?

Incised answered 8/11, 2009 at 5:22 Comment(4)
Very nice job indeed. I was just going to ask "what is the OS?" and suggest looking in the registry for cruft.Gnaw
@Keith: could you check the value type if you are still following this? Is the new value REG_EXPAND_SZ by any chance?Gnaw
@D.Shawley, read your update below. it was a preexisting REG_SZ in my case. I didn't delete the value - just modified it. HTH. Thanks.Incised
The problem is DEFINITELY caused (in all my VMs) whenever %* is missing. This becomes the case (problematic) when you use the Explorer method of associating a .pl file with your perl.exe program. When you do that it creates the 'command' key with a (Default) REG_SZ data value that is missing %* argument! I messed around for hours over this issue!Akeyla
G
9

Hmmm... sounds like the file association for *.pl is messed up somehow. I'm not on a Windows box, so I can't test this. You can check the file association stuff with either the ASSOC or FTYPE command on the command-line. IIRC, "ASSOC .pl" should tell you what the file type is and "FTYPE filetype command" tells the shell what to do with a Perl script. Try something like:

C:\> ASSOC .pl=perlscript
C:\> FTYPE perlscript=C:\Perl\bin\perl.exe %1 %*

From the looks of one of the command references that should do the trick. My guess is that the current association is not passing the parameters along to the script. You should be able to check that by using ASSOC .pl to figure out what the name of the file association is and then using FTYPE to print out the command that the shell is going to execute.

Update

I found an interesting thing that I want to note for posterity. I started seeing exactly this problem on a friends machine at work with respect to some Python scripts. ASSOC and FTYPE resulted in the expected output but the parameters were still not being passed along - exactly what was originally reported.

After a little digging, I found that the registry settings were created somewhere along the line as REG_SZ values. I deleted them and re-created them using ASSOC and FTYPE and everything started working... looking at the registry gave me the answer the new values were created as REG_EXPAND_SZ! These worked exactly as expected.

Gnaw answered 8/11, 2009 at 2:58 Comment(5)
The ftype was set to what you suggested. Well, nearly. The path to perl and %1 were quoted. I tried both ways without any luck. Thanks for the suggestions though.Incised
+1 - I didn't know about ASSOC and FTYPE. The commands you suggested worked just as advertised for me.Anamorphosis
@Keith Bentrup: Your ftype is probably missing the %* at the end. Look carefully. If that is not the problem, post the output of perl -VNudi
@Sinan, %* is definitely there. The output of -V is too much for the comment box, so I posted it here: pastebin.com/f148192a3Incised
@mobrule, where command line parameters passed? Was @ARGV not empty for a sample perl script that you tested? ftype and assoc are recognized commands that's not the problem. It's that the rest of the parameters (represented by %*) are not available in @ARGV.Incised
E
2

Update: Given that the following is correct, the only thing left to make sure is that command extensions are not turned off. Try:

cmd /e:on

on the command line before you run your tests. See also Windows XP cmd documentation:

Enabling and disabling command extensions

Command extensions are enabled by default in Windows XP. You can disable them for a particular process by using /e:off. You can enable or disable extensions for all cmd command-line options on a computer or user session by setting the following REG_DWORD values:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\EnableExtensions\REG_DWORD

HKEY_CURRENT_USER\Software\Microsoft\Command Processor\EnableExtensions\REG_DWORD

Set the REG_DWORD value to either 0x1 (that is, enabled) or 0x0 (that is, disabled) in the registry by using Regedit.exe. User-specified settings take precedence over computer settings, and command-line options take precedence over registry settings.

E:\Temp> assoc .pl
.pl=Perl
E:\Temp> ftype Perl
Perl="C:\opt\Perl\bin\perl.exe" "%1" %*
E:\Temp> @echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.PL;.PLX;.WPL;.py;.pyw
E:\Temp> cat t.pl
print "'$_'\n" for @ARGV;
E:\Temp> t a b c d e f g h j
'a'
'b'
'c'
'd'
'e'
'f'
'g'
'h'
'j'

I have used pretty much every ActiveState Perl distribution since 2004. These settings are enough to make it work.

Elongation answered 8/11, 2009 at 3:45 Comment(2)
+1, Thx for a simple test case. Unfortunately, my box behaves differently.Incised
Thanks for the continued help, Sinan. It did not fix the behavior, but I found a solution.Incised
M
2

To sum up.

ftype is old and cmd.exe doesn't care whatever it says.

The real deal is the HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command thing.

Just run: reg add HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command /ve /d "C:\strawberry\perl\bin\perl.exe \"%1\" %*" /f

and everything will be ok. (* given that "C:\strawberry\perl\bin\perl.exe" is the exact path to your Perl installation.*)

/ve is meant to work on de “(Default)” REG_SZ value /d is to assign “data” to the “value” /f to force substitution (or overwriting) of the preexisting value

In fact, if assoc .pl=Whatever and ftype Whatever doesn't exist (never assigning a value to it, or doing ftype Whatever= to unassign), the scripts could still be invoked without prepending perl.exe.

So, if using Windows >= 6.0 (Windows Vista, Windows Server 2008, Windows 7, etc.) just forget that the commands assoc and ftype exist at all. Don't bother. Go reg.exe!

Metacarpus answered 6/3, 2011 at 16:11 Comment(0)
G
0

I tried updating and associating .pl with the many different Perl entries in the registry that others have tried (.pl, Perl, PerlScript, pl_auto_file, Applications\perl.exe) and none of these worked. I'm running ActiveState Perl 5.14.2 on Windows 7. I then noted that there was an entry for \Applications\perl5.14.2.exe in the registry and it was set to:

"C:\Perl\bin\perl5.14.2.exe" "%1"

Added the %* to this and then I was able to see data in @ARGV.

I also noted that on some of these entries I had a command path entry of "C"\Perl64\..." from a previous 64 bit Perl that I'd installed earlier and uninstalled when I found out that 64 bit Perl isn't as nice with IIS 7 as 32 bit Perl is. So there are dangling installation remnants that are probably affecting things too.

So the answer here is probably not a short one and is in simple words... "It depends..." (on your system and installation).

Glycolysis answered 8/3, 2012 at 23:44 Comment(0)
B
0

After fixing the file association problem, I could not pass parameters. A user I support mistakenly associated the .pl file extension with Notepad after trying to run the script from the (Windows 7 Professional) command line for the first time.

We tried all the file association tricks and environment variable fixes to no avail. We uninstalled and reinstalled and tried 32 bit and 64 bit installations. The issue was only present on the user's profile.

Finally we went into the registry and simply deleted the key from:

HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command

And added back via:

reg add HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command /ve /d "C:\strawberry\perl\bin\perl.exe "%1" %*" /f

It started passing parameters again.

Bergquist answered 18/12, 2013 at 20:52 Comment(0)
G
0

I found this additional location in the registry that had to be updated before it would work for me. Note: The name after HKEY_USERS may be different on your machine.


Add %* to default string:


HKEY_USERS\S-1-5-21-1399284159-2775065347-350672949-4058_Classes\pl_auto_file\shell\open\command "D:\Perl\bin\perl.exe" "%1" %*

Goulet answered 23/3, 2017 at 16:51 Comment(0)
E
0

The original author's answer works.

Here's a complete registry file for manually installing Perl on Windows. Just add this to the PATH environment variable: ";C:\PERL\bin;" and make a perl.reg file with Notepad containing this:

Windows Registry Editor Version 5.00

[-HKEY_CLASSES_ROOT\.pl]
[HKEY_CLASSES_ROOT\.pl]
@="Perl"
"PerceivedType"="text"
[HKEY_CLASSES_ROOT\.pl\Perl]
[HKEY_CLASSES_ROOT\.pl\Perl\ShellNew]
[HKEY_CLASSES_ROOT\.pl\PersistentHandler]
@="{5e941d80-bf96-11cd-b579-08002b30bfeb}"

[HKEY_CLASSES_ROOT\Applications\perl.exe]
[HKEY_CLASSES_ROOT\Applications\perl.exe\shell]
[HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open]
[HKEY_CLASSES_ROOT\Applications\perl.exe\shell\open\command]
@="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"

[HKEY_CLASSES_ROOT\Perl]
[HKEY_CLASSES_ROOT\Perl\shell]
[HKEY_CLASSES_ROOT\Perl\shell\Open]
[HKEY_CLASSES_ROOT\Perl\shell\Open\command]
@="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"

[HKEY_CLASSES_ROOT\pl_auto_file]
@=""
[HKEY_CLASSES_ROOT\pl_auto_file\shell]
[HKEY_CLASSES_ROOT\pl_auto_file\shell\open]
[HKEY_CLASSES_ROOT\pl_auto_file\shell\open\command]
@="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"

[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe]
[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe\shell]
[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe\shell\open]
[HKEY_CURRENT_USER\Software\Classes\Applications\perl.exe\shell\open\command]
@="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"

[-HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl\OpenWithList]
"a"="perl.exe"
"MRUList"="ab"
"b"="NOTEPAD.EXE"
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl\OpenWithProgids]
"pl_auto_file"=hex(0):
"Perl"=hex(0):

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl\shell]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl\shell\Open]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Perl\shell\Open\command]
@="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file]
@=""
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file\shell]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file\shell\open]
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pl_auto_file\shell\open\command]
@="\"C:\\Perl\\bin\\perl.exe\" \"%1\" %*"

[HKEY_LOCAL_MACHINE\SOFTWARE\Perl]
@="C:\\PERL\\"
"BinDir"="C:\\Perl\\bin\\perl.exe"
Elsa answered 20/1, 2019 at 1:36 Comment(0)
P
0

I installed Perl 5.24.3 on Windows Server 2016 and found the JAMS Scheduler Agent Shell ignored the .pl extension as if it did not exist. All was good from DOS desktop.

The same configuration on Windows Server 2008 worked fine. The registry entries created by that ActiveState Perl Install, matched Lucretius' post, but do not apply globally to all users. Not the default system user for example.

Logging in as the user the Shell will run as, and making the association helped.

Ideally, there would be a registry tweak to make .pl assoc global(?).

Plosive answered 3/11, 2019 at 1:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.