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):
1 2 3 4 5 6 7 8 9 10 11 |
>echo echo This is: %0 > test.bat.bat >test.bat.bat >echo This is: test.bat.bat This is: test.bat.bat >test.bat >echo This is: test.bat This is: test.bat |
Then, if there is no extension, the behaviour of the Command Prompt and its START
command differ. The Command Prompt reports (with ERRORLEVEL
9009):
1 2 3 |
>myApp 'myApp' is not recognized as an internal or external command, operable program or batch file. |
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:
1 2 |
>set PATHEXT PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC |
.COM
is used to name five executables, for compatability with legacy Windows:
1 2 3 4 5 6 |
>where *.com C:\Windows\System32\chcp.com C:\Windows\System32\format.com C:\Windows\System32\mode.com C:\Windows\System32\more.com C:\Windows\System32\tree.com |
.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:
1 2 3 4 5 |
>ASSOC .VBS .VBS=VBSFile >FTYPE VBSFile VBSFile="%SystemRoot%\System32\WScript.exe" "%1" %* |
.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
).
1 2 3 4 5 |
>ASSOC .MSC .MSC=MSCFile >FTYPE MSCFile MSCFile="%SystemRoot%\System32\mmc.exe" "%1" %* |
Powershell 5
On my Windows 10 machines, the default value of PATHEXT
in Powershell 5 is:
1 2 |
PS> $env:PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL |
.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.