Today I installed Strawberry Perl on my Lenovo Helix. Now my little bitty Helix is going to give me some trouble sometime soon because it is still running Windows 8.1. I’ve not decided whether I will try installing Windows 10 (I’m not sure it will run Windows 11) or whether I will go Linux. I kinda like having at least one Windows box around for things I just don’t care enough to bully into working on Linux. On the other hand, I really don’t want to pay for Windows.
Until I solve that moral dilemma, I thought I’d make it into something of a portable playground. Portable in the sense of no internet required. For some reason, I keep finding myself in such places these days. So I installed a couple things including Strawberry Perl. Now, it’s been quite a long time since I’ve done any serious programming, let alone Perl and Perl on Windows. Most of my IT experience has been *nix. On the Windows side of Perl things, I’ve used (in the past) Active State, Cygwin and MinGW. I’ll be honest, I’ve never been overly happy with any of them. Trying to add *nix environment to Windows has always been a bit quirky (including the newish WSL). On the other cake eating hand, Active State never seemed to play well with my *nixy needs, particularly CPAN.
Yes, I know these things get better and in many cases there are ways to bully them harder into working the way you want. But before I decided to do all that again, I thought I’d give Strawberry Perl a chance.
I’ll not spend time on the installation. It worked just like the documentation on the site says it will. Opening a PowerShell window and checking the version of Perl gets you this:
PS C:\Users\Robert> perl --version This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread Copyright 1987-2021, Larry Wall Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5 source kit. Complete documentation for Perl, including FAQ lists, should be found on this system using "man perl" or "perldoc perl". If you have access to the Internet, point your browser at http://www.perl.org/, the Perl Home Page. PS C:\Users\Robert>
You can do this in a Windows Command prompt also, but I’m showing you PowerShell for a reason I’ll get to later. It’s also worthwhile taking a quick peruse of the install. If you changed no defaults, it should have installed to C:\Strawberry\. Looking at the perl subdirectory you should see the following:
In the bin directory, you’ll find all the Perl executables. Some noteworthy ones are, of course, the perl executable, cpanm, perldoc, perltidy and so much more. You might also notice there seems to be two of most everything. There will be a file with either no extension, or .pl extension and a matching file with a .bat extension. A bit more on this later.
The lib, site and vendor directories are important as these are where all your installed Perl modules will be. Thus, if it ain’t in here, it ain’t installed. Conversely, when you install a new module, it should appear in one of these three subdirectories. It’s worth noting the site directory also has its own bin directory.
Now, I could Hello World right now, but like I said, I wanted to see how some other things worked out first, especially CPAN. Being both fearless and foolish, I decided to start with Perl/Tk. I opened up a PowerShell terminal and bravely executed cpanm Tk. After a somewhat nervously long amount of time, imagine my joy when GUI widgets started flashing on my screen. It was working! When I finally got my cursor back, I scanned the following:
Files=76, Tests=4602, 57 wallclock secs ( 0.62 usr + 0.27 sys = 0.89 CPU) Result: FAIL Failed 2/76 test programs. 2/4602 subtests failed. gmake: *** [Makefile:1452: test_dynamic] Error 255 -> FAIL Installing Tk failed. See C:\Users\Robert\.cpanm\work\1683945545.9796\build.log for details. Retry with --force to force install it.
Well nuts! I googled about for a bit, somewhat half heartedly but made one discovery and one decision. First, I decided to take the advice offered by the above message. I ran cpanm again with the force option. After all, it only failed two measly tests out of 4,602. That’s a pretty darn fine score I think! Well, maybe not, it’s not clean, but I decided it was good enough to get started and I’d figure the errors out later.
The discovery was the Prima module and also part of why I elected to just force the Tk module. Now I remember Prima from way back in the day. I invited them to an OS/2 conference back when Prima started out on OS/2. As I recall, they were only billing themselves as a Visual Builder. Needless to say, I was quite pleased to see their framework not only released as just any other module, but also that it seems to still be under development. Turns out, they still have the Visual Builder bundled in as well. The Prima module installed without a hitch.
It was now time to say “hello” to the world.
I had previously installed the Microsoft VSCode editor with the Perl Navigator and perl-outline extensions (all pointy and clicky) so I felt ready to go. Actually, I had to install ctags and Perl::Critic so maybe I’ll post about my VSCode setup sometime later… I created my HelloPerl directory and workspace and my hello.pl file.
#!C:\Strawberry\perl\bin\perl.exe -w use strict; use warnings; print("Hello World!\n");
With glee and anticipation, I hopped down to the terminal window in VSCode and typed hello.pl and. nothin’… urrrggg…. Fine. I typed perl hello.pl
PS C:\Dev\HelloPerl> perl hello.pl Hello World! PS C:\Dev\HelloPerl>
Okay, so it worked, but I wasn’t happy. With the shebang line, I thought I shouldn’t have to invoke perl first. I also don’t ever remember having to do that on Windows before. Time to test my Google-fu again.
I found out a couple things in my search. First, remember when I said earlier I opened a PowerShell terminal to test things? The reason I did that is because, as you might notice from the snippet above, the default terminal in VSCode is PowerShell! and yes, PowerShell and Command are not the same. For instance, if you try invoking a shell script directly in PowerShell you get something like the following:
PS C:\dev\HelloPerl> hello.pl hello.pl : The term 'hello.pl' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:1 + hello.pl + ~~~~~~~~ + CategoryInfo : ObjectNotFound: (hello.pl:String) , CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException Suggestion [3,General]: The command hello.pl was not found, but does exist in the current location. Windows PowerShell does not load commands from the current location by default. If you trust this command, instead type ".\hello.pl". See "get-help about_Command_Precedence" for more details. PS C:\dev\HelloPerl>
The important part is there at the end. PowerShell does not include the current directory in its execution path.
The second thing I discovered was the reason for all those batch files I mentioned earlier. My web searching turned up the common advice to use pl2bat to create a batch shell wrapper for each Perl script. ewwwww… I half remember that, but still thought it should not be necessary. If you’re curious though, the pl2bat script is located in C:\Strawberry\perl\bin, and yes, it has a batch file wrapper for itself.
So I searched harder and I found this post on StackOverflow. First we need to associate *.pl files with perl. Open an Administrative Command terminal and type the following:
assoc .pl=PerlScript ftype PerlScript=C:\Strawberry\perl\bin\perl.exe "%1" %*
Next you need to set your Environmental Path variables. Depending on your version of Windows, you should be able find this by opening Windows Explorer, right clicking on This PC, selecting Advanced System Settings, the Advanced tab and then the Environment Variables button. The second window has the system wide variables. C:\Strawberry\perl\bin should already be in the Path environment variable (otherwise the perl –version command earlier would not have worked). The other item needed is to add ;.PL to the end of the PATHEXT environment variable. Save then exit. Note: This can also be done in the Administrative Command window with the following command:
setx PATHEXT %PATHEXT%;.PL
Now, you can open either a Windows PowerShell terminal, or use the terminal window in VSCode:
PS C:\dev\HelloPerl> .\hello.pl Hello World! PS C:\dev\HelloPerl>
Now, the other suggestions in that article I did not use. The registry change to accept piped input seems to have not been necessary on Windows 8.1. We can test this by the changing our script slightly.
#!C:\Strawberry\perl\bin\perl.exe -w use strict; use warnings; print(<STDIN> . "\n");
Run the script again in PowerShell (or the VS Code Terminal).
PS C:\dev\HelloPerl> echo "Hello World!" | .\hello.pl Hello World! PS C:\dev\HelloPerl>
The last suggestion, using drag and drop just seemed to weird to bother with. Does anyone actually drag and drop a script onto an executable to run it?
So the final thing was to get rid of the need to preface our script with ‘.\’ to run it. Now I’ll admit, I got a little gun-shy about this one. The answers I found were so varied and seemed so needlessly complex I started second guessing myself and wondering if I really should do this or not. After all, why is that the default behavior and why is it not as simple as using the same path already set, just like the Command shell does?
In the end, I just couldn’t really figure out why this was the default behavior. Security? That would mean there were legions of hackers out there, pulling their hair out because they could not figure out how to add “.\” to that final command that would execute their genius hack. Safety? Well, I had already done enough to undo that. I could even double click now to run a script. In all, it seemed it was there just to irritate me. So I made a pinky swear with myself to be careful (like I have been on every *nix system I’ve ever worked on for some thirty-five years) and executed the following in an Administrative PowerShell terminal:
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";.", [System.EnvironmentVariableTarget]::Machine)
I rebooted my laptop, opened a PowerShell terminal, and walla!
Windows PowerShell Copyright (C) 2014 Microsoft Corporation. All rights reserved. PS C:\Users\Robert> cd C:\dev\HelloPerl PS C:\dev\HelloPerl> hello.pl Hello World!!! PS C:\dev\HelloPerl>