Portable Perl Applications on Windows

Deploying a Perl based application to Windows users raises the question of whether and how to bundle the required Perl runtime and libraries.

If you don't want to force the user to install a Perl distribution, the usual answer is: "Use a Perl packer".

"pp", probably the most common packer among them, creates a single exe. I think the design choice for a "one-file solution" was not based on objective requirements analysis. I will provide a simpler solution below.

Requirements

That's my idea of important requirements:

  • The application must be located in a directory tree freely specified by the user. Rationale: The user can decide whether or not to have it write-protected, and the installation is transparent to the user.
  • The application shall be (optionally) reachable via the search path.
  • The application should be "portable": Unpack it somewhere and it runs without any configuration or patching.
  • Calling the application shall be simple, appname.exe instead of "perl.exe appname.pl"

Apart from that, I prefer solutions to be as simple as possible.

Simply bundle everything with a smart launcher .exe

From a system perspective, the simplest method is to bundle all required files in one directory tree and provide an appname.exe calling the Perl interpreter.

The perl.exe of current Perl distributions does hardly more than "RunPerl(argc, argv, env);" But it's a bit awkward to call "installpath\perl.exe installpath\appname.pl".

A smart(er) launcher just needs to:

  • Get its own full path with GetModuleFileName();
  • Replace ".exe" with ".pl"
  • And add this path to the RunPerl() parameters

Name it "appname.exe" and place it next to appname.pl (and the Perl DLLs). Then you can call it from anywhere, like any other "native" Windows application.

To avoid collisions of additional files (e.g. libraries), use a configuration where the Perl script and DLL are located in a specific subdirectory. The "installation directory" will then only contain appname.exe and a directory "appname_files", holding all the other required files.

Download

Get a demo and C code here: ppl.zip Use at your own risk!

The archive contains also a rudimentary unpar.cmd for automatic unpacking of executables generated by PAR/pp, but this won't work for every pp packed exe. Find a much better pp unpacker further down this page.

A full ExifTool installer using Strawberry Perl is available here: ExifTool-for-Windows

Perl Packers

Free, open source:

Free, closed source:

Commercial:

Potential problems using the PAR Packer pp

The PAR Packager "pp" authors write 'You may think of pp as "perlcc that works without hassle". :-)'.

I have to admit that the prospect of a monolithic exe, created by a simple command, is tempting.

But at least for Windows, pp doesn't seem that reliable to me. Users of popular tools using pp (Biber, ExifTool and dependent programs) are experiencing problems regularly.

The usual reflex is to blame "the bad Windows" and Defender. Users are advised to run the application as administrator and to disable Defender. That's easily said but the wrong approach.

As far as I see, pp itself is the cause of many problems, here are some reasons:

Using the temp directory for executables

pp does not create a real monolithic exe, but rather a self-extracting archive, unpacking executables and scripts to the Windows temp directory. This design choice has some bad consequences:

  • Unwanted change or removal of extracted files, e.g. by maintenance tools (cleaners) or even malware.
  • Running executables in is the same method that Emotet uses and considered suspicious by many AV products and even might be blocked by system policies.
  • It's cluttering temp with old versions since there is no "uninstaller", and most users are not aware of the hidden unpacking.

Users are often advised to set PAR_GLOBAL_TEMP, but this causes other problems and is "discouraged" according to the maintainer.

There were patches tinkering with symptoms, e.g. "biber" files vanished from the cache directory, but not solving the root problem: Executables shall not reside in the "temp" folder!

Setting an incompatible environment

pp sets Perl variables in an unexpected manner. For example, $0 contains the name of the exe instead of the script name which will break existing path calculations in your application. $^X is set to "perl.exe" (but there is no perl.exe) and @INC has garbage entries.

Complicated boot process

The pp boot process runs a first Perl interpreter by passing a 20KB "one liner" (!) and then spawns a second process, using several environment variables and mangled command line arguments.

One problem with this is that the actual working Perl process always gets the priority "BelowNormal" and you can't change that (according to https://exiftool.org/forum/index.php?topic=15152.0)

Embedding non-portable Perl configuration

pp copies "non-portable" configuration data from the Perl installation to the resulting archive, e.g. "config.pm" usually contains many absolute paths and other settings. This is no pp-specific problem but it's easy to overlook since pp promises automatic resolution.

Incomplete dependency resolving

The PAR Packer doesn't (can't) resolve all dependencies automatically. Depending on the complexity of the app, it may take many bug reports from users until every needed module or other file is added manually. That's also a problem of other solutions.

Stability / reliability

pp is not exactly the most beautiful code ever written. Don't look at it if you are faint-hearted. Roderich Schupp once wrote: "the code base is very brittle and prone to breaking stuff at a distance".

Using pp to create a portable package

Even though the runtime part of pp has some problems, pp is smart in collecting the needed files. But as far as I know, you can't ask pp not to hiding them in the archive.

Johan Vromans aka "sciurius", the developer of ChordPro, made a tool to unpack a .exe archive created by pp:

https://github.com/ChordPro/chordpro/blob/dev/pp/pp2ppl.pl

You can then use the extracted file tree together with the simple launcher presented here.