How does windows decide which executable to run
I have several places on my computer that have executables, and they are all added to the PATH
.
Occasionally, there are cases where I have multiple executables with the same name that either have different configurations or do different things entirely. For example I have the native Windows FIND
command, and I also have the Linux port of find
for windows. Both of these are very useful in their own right, but do very different things.
When I execute FIND
from the command line; by default the Windows version executes unless I am in the directory with the Unix version. In this case, this is mostly what I want, but there are situations that are different. I know the executable that will run will always be the one outputted when I type which <executable name>
.
My question is: How is that executable chosen over the other? Why does Windows choose Git
located at ...\msysgit\bin\git.exe
vs the one located at D:\bin\git.exe
? Both locations are on the PATH
. Is it something as silly as the order of the PATH
entries?
Solution 1:
Windows first checks the current working directory, then checks each path in the PATH variable from left to right, and finally checks system locations (e.g. %WINDIR%). This is almost identical to Linux, except Linux does not check "." before PATH.
Solution 2:
What Windows will execute is not trivial, it might even depend on the API used.
One of them is CreateProcessW which documents:
- The directory from which the application loaded.
- The current directory for the parent process.
- The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
- The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
- The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
- The directories that are listed in the PATH environment variable. Note that this function does not search the per-application path specified by the App Paths registry key. To include this per-application path in the search sequence, use the ShellExecute function.
Since Windows Vista, the environment variable %NoDefaultCurrentDirectoryInExePath% configures whether or not the current directory should be searched (Source: MSDN).
Also: if you just run a command without an extension, the environment variable %PathExt% is used to find executable extensions. (Source: MSDN).
The default value for the PATHEXT variable is: .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
The text of CreateProcessW mentions ShellExecute, but I could not find documentation of how that function deals with path settings.
A great tool for figuring out where exactly an executable is searched is SysInternals Process Monitor. Set a filter for path contains <executable>
(not <executable>.exe
) and you'll see the exact search order. It will report "NO SUCH FILE" for directories which do not contain an executable.