The more you study …

Trying to make Haskell-related things work on Windows, you can learn a lot about Unix-like operating systems. Sometimes you can learn about Windows too. Looking at RIO.Process.findExecutable provided by rio-0.1.12.0, I learnt about the PATHEXT environment variable.

PATH and PATHEXT

The Command Prompt (cmd.exe) and other executables use the environment variables PATH and PATHEXT to look for a file, given incomplete information. The value of PATH is a list of paths, delimited by semi-colons. The value of PATHEXT is a list of file name extensions (including the initial .), similarly delimited.

To emulate the behaviour of those executables – for example, in the case of findExecutable – it is necessary to understand how they behave.

Microsoft documents the PATHEXT variable in the START command of Command Prompt. It also refers to it in the documentation of the WHERE executable.

If a path is not specified, the Command Prompt and its START command search in the current folder and then in each path in PATH in turn (from left to right).

For each folder in question, if there is no extension, or no direct match if there is an extension, the Command Prompt and its START command search for a file name by adding each extension in PATHEXT in turn (from left to right).

For example (START behaves in the same way):

Then, if there is no extension, the behaviour of the Command Prompt and its START command differ. The Command Prompt reports (with ERRORLEVEL 9009):

This behaviour means that an executable with a filename without an extension cannot be run from the Command Prompt.

However, if there is no extension, such a file exists and no file type is associated with no extension (the default), the START command reports (with ERRORLEVEL 9020) that ‘The system cannot execute the specified program.’.

If there is no extension, a file type associated with no extension, and such a file exists, the START command ‘starts’ the file using the association.

If there is no extension and such a directory exists, the START command ‘starts’ explorer.exe with the directory.

On the other hand, WHERE searches in the current folder and then in each path in PATH in turn. For each folder in question, it searches for the pattern and the pattern by adding each extension in PATHEXT in turn. This behaviour means that an executable with a filename without an extension can be located by ‘where’.

Command Prompt

On my Windows 10 machines, the default value of PATH at the Command Prompt is:

.COM is used to name five executables, for compatability with legacy Windows:

.EXE is the familiar extension for executables on Windows.

.BAT and .CMD are extensions for batch files.

.VBS and .VBE are extensions for VBScript script files, the latter being an encoded variety; .JS and .JSE are extensions for JScript files, the latter being an encoded variety; and .WSF and .WSH are extensions for a Windows Script file and a Windows Script Host file, respectively. On my machines, all are associated with Windows Script Host (WScript.exe) by default. For example:

.MSC is the extension for a management saved console snap-in for use with the Microsoft Management Console. On my machine it is associated with Microsoft Management Console (mmc.exe).

Powershell 5

On my Windows 10 machines, the default value of PATHEXT in Powershell 5 is:

.CPL is the extension for a Control Panel file.

Powershell Core 6.2.4

On my Windows 10 machines, the default value of PATHEXT in Powershell Core 6.2.4 is the same as at the Command Prompt; it does not include .CPL. That is considered an error and will be rectified in version 7.0.0.