1

I looked for this question over the site but it looks like it's never been asked, so I thought I would share the answer to anyone looking for it.

Q: When I input executables files' name in cmd.exe, through shell-execution functions or from a Batch file, how does Windows locate the external executable file to be called?

noize
  • 93
  • 1
  • 8

3 Answers3

3

I do not understand what "shell-execution function" is referring to, so I will ignore it.

But the rules for launching an executable from the CMD.EXE command line, or from a batch file are as follows:

  1. If a path is specified for the executable (absolute or relative), then only that path is searched.

  2. If only the executable name (and possibly extension) is specified, then

    • First search the current folder

    • Then search folders in PATH environment variable (in order listed)

  3. Within each folder searched, use the provided extension. If no file extension is provided, then look for files that match extensions found in PATHEXT environment variable (in order listed).

The first matching file found is the one that gets executed.


EDIT

David Candy has pointed me to some outdated NT documentation that precisely outlines the search process, and it essentially matches what I have written above. See Launching Applications from the NT Shell

I'd love it if anyone could post links to similar CMD.EXE documentation for more recent versions of Windows, especially if it was written by Microsoft. Note that the NT doc linked above was not written by Microsoft, even though it is posted on their site.

dbenham
  • 127,446
  • 28
  • 251
  • 390
  • 1
    +1. I think the poster might be referring to `ShellExecute/ShellExecuteEx`, but it doesn't matter as the OP is asking about what happens in the command shell either way (it mentions using `cmd.exe` specifically). – Ken White Nov 19 '13 at 23:31
  • +1 for the link. If the name has no path; it is first matched against the internal commands list e.g., dir, copy, time. – jfs Aug 06 '14 at 19:23
  • @J.F.Sebastian - But the question explicitly asks how CMD.EXE locates ***external*** executables. Besides, I believe the rules for differentiating between internal and external commands are more complex than your comment implies. For example, `echo.bat` will execute the internal ECHO command and print `bat` to the screen if no "echo.bat" file exists. But if file "echo.bat" does exist, then the batch script is executed instead of the internal command. But `echo text` will always execute the internal command, even if file "echo.bat" exists. – dbenham Aug 06 '14 at 20:02
  • @dbenham: yes, the question is about *external* executables but you must know about **internal** commands to avoid the accidental name conflict. And if the rules are even more complex as you suggest: the more reasons to mention the possible conflict with internal commands. – jfs Aug 06 '14 at 20:08
  • This is probably more precise: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx – noize Dec 22 '15 at 02:48
  • @noize - Absolutely not. The rules in your link are specifically for dynamic link libraries (DLLs) - definitely different than the rules CMD.EXE uses to find external programs. – dbenham Dec 22 '15 at 06:37
  • No, yeah, you're right. That was not the right document. I had also written a paper mentioning pretty much the same answer as yours ( https://www.sinister.ly/Thread-Paper-Understanding-Windows-PATH-and-privilege-escalation ), though I can't find the Microsoft documentation, unluckily. – noize Dec 22 '15 at 11:10
0

Here's a debug of CMD using CreateProcessW to start edit.com.

Microsoft (R) Windows Debugger Version 6.2.9200.20512 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: C:\Windows\System32\cmd.exe
Symbol search path is: srv*C:\tmp*http://msdl.microsoft.com/download/symbols;c:\tmp
Executable search path is: 
ModLoad: 49fe0000 4a030000   cmd.exe 
ModLoad: 76dd0000 76ef7000   ntdll.dll
ModLoad: 75860000 7593b000   C:\Windows\system32\kernel32.dll
ModLoad: 76a20000 76ae6000   C:\Windows\system32\ADVAPI32.dll
ModLoad: 76d00000 76dc2000   C:\Windows\system32\RPCRT4.dll
ModLoad: 75b20000 75bca000   C:\Windows\system32\msvcrt.dll
(58c.918): Break instruction exception - code 80000003 (first chance)
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll - 
eax=00000000 ebx=00000000 ecx=0027f9a0 edx=76e29a94 esi=fffffffe edi=76e2b6f8
eip=76e17dfe esp=0027f9b8 ebp=0027f9e8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
76e17dfe cc              int     3
0:000> bp kernel32!CreateProcessW
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\kernel32.dll - 
breakpoint 0 redefined
0:000> g
Breakpoint 0 hit
eax=0027f590 ebx=00000000 ecx=00000000 edx=00000000 esi=4a005200 edi=00000001
eip=75861c01 esp=0027f4b4 ebp=0027f674 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
kernel32!CreateProcessW:
75861c01 8bff            mov     edi,edi
0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
0027f4b0 49fe4568 00316078 003175a8 00000000 kernel32!CreateProcessW
0027f674 49fe4315 00317508 00000000 00000000 cmd!ExecPgm+0x20a
0027f8d4 49fe43a8 00317508 00000000 00000000 cmd!ECWork+0x7f
0027f8ec 49fe43ce 00317508 e3a3ec47 00000001 cmd!ExtCom+0x47
0027fd48 49fe185f 00317508 00000002 7588372f cmd!FindFixAndRun+0xb3
0027fd98 49ff70d4 00000000 00317508 4a0041b0 cmd!Dispatch+0x14a
0027fddc 49fe985b 00000001 000a0f38 000a1840 cmd!main+0x21a
0027fe20 758a4911 7ffdb000 0027fe6c 76e0e4b6 cmd!_initterm_e+0x163
0027fe2c 76e0e4b6 7ffdb000 7871d1d4 00000000 kernel32!BaseThreadInitThunk+0x12
0027fe6c 76e0e489 49fe9797 7ffdb000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0027fe84 00000000 49fe9797 7ffdb000 00000000 ntdll!RtlInitializeExceptionChain+0x36
0:000> du 316078
00316078  "C:\Windows\system32\edit.com"
David Candy
  • 735
  • 5
  • 8
-3

See CreateProcess.

  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. Windows Me/98/95: The 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.
David Candy
  • 735
  • 5
  • 8
  • @dbenham This is flawed when launching files from the cmd prompt and does not answer the question - the proof was in the comments that have now been disingenuously removed. – foxidrive Nov 21 '13 at 04:29