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:

  1. The directory from which the application loaded.
  2. The current directory for the parent process.
  3. The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
  4. 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.
  5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  6. 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.