How is it possible to run Wordpad by just typing its name even though it isn’t on the PATH?


In a comment completely unrelated to the topic, Chris Capel asks how Wordpad manages to run when you type its name into the Run dialog even though the command prompt can't find it? In other words, the Run dialog manages to find Wordpad even though it's not on the PATH.

Chris was unable to find anywhere I discussed this issue earlier, but it's there, just with Internet Explorer as the application instead of Wordpad.

It's through the magic of App Paths.

App Paths was introduced in Windows 95 to address the path pollution problem. Prior to the introduction of App Paths, typing the name of a program without a fully-qualified path resulted in a search along the path, and if it wasn't found, then that was the end of that. File not found. As a result, it became common practice for programs, as part of their installation, to edit the user's AUTOEXEC.BAT and add the application's installation directory to the path.

This had a few problems.

First of all, editing AUTOEXEC.BAT is decidedlly nontrivial since batch files can have control flow logic like IF and CALL and GOTO. Finding the right SET PATH=... or PATH ... command is an exercise in code coverage analysis, especially since MS-DOS 6 added multi-config support to CONFIG.SYS, so the value of the CONFIG environment variable is determined at runtime. If you wanted to avoid hanging your setup program, you would have to solve the Halting Problem. (You can't just stick at PATH ... at the beginning because it might get wiped out by a later PATH command, and you can't just stick it at the end, because control might never reach last line of the batch file.)

And of course, very few uninstall programs would take the time to undo the edits the installer performed, and even if they tried, there's no guarantee that the undo would be successful, since the user (or another installer!) may have edited the AUTOEXEC.BAT file in the meantime.

Even if you postulate the existence of the AUTOEXEC.BAT editing fairy who magically edits your AUTOEXEC.BAT for you, you still run into the PATH length limit. The maximum length of a command line was 128 characters in MS-DOS, and if each program added itself to the PATH, it wouldn't be long before the PATH reached its maximum length.

Pre-emptive Yuhong Bao irrelevant detail that has no effect on the story: Windows 95 increased the maximum command line length, but the program being launched needed to know where to look for the "long command line". And that didn't help existing installers which were written against the old 128-character limit. Give them an AUTOEXEC.BAT with a line longer than 128 characters and you had a good chance that you'd hit a buffer overflow bug.

On top of the difficulty of adding more directories to the PATH, there was the recognition that this was another case of using a global setting to solve a local problem. It seemed wasteful to add a directory to the path just so you could find one file. Each additional directory on the path slowed down path sarching operations, even the ones unrelated to locating that one program.

Enter App Paths. The idea here is that instead of adding your application directory to the path, you just create an entry under the App Paths key saying, "If somebody is looking to execute contoso.exe, I put it over here." Instead of adding an entire directory to the path, you just add a single file, and it's used only for application execution purposes, so it doesn't slow down other path search operations like loading DLLs.

(Note that the old documentation on App Paths has been superseded by the new documentation linked above.)

Now that there was a place to store information associated with a particular application, you may as well use it for other stuff as well. A secondary source of path pollution came from applications which added not only the application directory to the path, but also a helper directory where the application kept its DLLs. To address this, an additional Path value specified which directories your application wanted to be added to the path before it was executed. Over time, additional attributes were added to the App Paths key, such as the UseUrl value we saw some time ago.

When you type the name of a program into the Run dialog (with no path), the Shell­Execute function checks if the name corresponds to an application registered under App Paths. If so, then it uses the registration information to launch the application. Hooray, applications can be run by just typing their name without requiring them to modify the global path.

Note that this extra lookup is performed only by the Sh­ellExecute family of functions, so if you use Create­Process or Search­Path, you'll still get ERROR_FILE_NOT_FOUND.

Now, the intent was that the registered full path to the application is the same as the registered short name, just with a full path in front. For example, wordpad.exe registers the full path of %ProgramFiles%\Windows NT\Accessories\WORDPAD.EXE. But there's no check that the two file names match. The Pbrush folks took advantage of this by registering an application path entry for pbrush.exe with a full path of %SystemRoot%\System32\mspaint.exe: That way, when somebody types pbrush into the Run dialog, they get redirected to mspaint.exe.

Sneaky.

Comments (29)
  1. Helge Klein says:

    For once, I wrote about something before Raymond ;-) Here is my take on App Paths: helgeklein.com/…/how-the-app-paths-registry-key-makes-windows-both-faster-and-safer

  2. Dan Bugglin says:

    I always wondered why there was no pbrush.exe stub for old programs.  Now I know why… shellexecute will still work for legacy apps that want to launch paint.

  3. NB says:

    Raymond, do you frown upon what the PBrush folks used App Paths for?

  4. VirtualBlackFox says:

    Sadly as the console doesn't support them command line programs still need to rely on PATH and expose all files in their directories (As they did for years anyway)

  5. Joshua Ganes says:

    You mention that this will not work if you call CreateProcess or similar. Was this intentional? If so, was it to address compatibility, to save development time, or was it a technical limitation?

  6. Joshua says:

    As you probably know, cmd.exe resolves App Paths as well. It's obviously not using ShellExecute as it passes command lines.

  7. MikeCaron says:

    Joshua – my guess is to prevent something like

    CreateProcess("myHelper.exe");

    from executing "C:someOtherProgrammyHelper.exe" rather then their own "myHelper.exe". (If you are using ShellExecute, it implies that you're executing an action like a User would. If you're using CreateProcess, you're executing an action like a cold, unfeeling program which is expected to supply the full path)

  8. JM says:

    @VirtualBlackFox: that's what the START built-in is for. I think it's been around since Windows 95, same as app paths (but I might be wrong).

    @Joshua (2nd): I don't know what cmd.exe you're using, but mine doesn't resolve App Paths if I just enter an executable name. What cmd.exe does do (even without START) is launch documents based on their extensions, but this requires that the document in question is on the search path.

  9. Evan says:

    @Mike Caron: Except that (at least according to Helge Klein's post) 'App Paths' is the last place consulted for 'myHelper.exe'.

    It also has the (unfortunate?) side effect that App Paths is apparently not consulted when running a program from cmd.exe (try running pbrush from there).

  10. ChuckOp says:

    Presumably you don't want to mess with console behavior with something that is very specific to Windows and the shell.

    You can get the behavior in the console by using the START command:

    cd

    REM This won't work

    wordpad.exe

    REM This will work

    start wordpad.exe

    [Second attempt to post comment]

  11. SimonRev says:

    Fortunately 4NT at least handles AppPaths.  I actually didn't know that pbrush was a "redirect" to mspaint.exe, but lo and behold, I type in "which pbrush" in 4NT this morning and it prints out "pbrush is an external : C:WINDOWSsystem32mspaint.exe"

  12. Troll says:

    App paths is one of the coolest features in Windows and Microsoft has done a very poor job of making developers and users aware of it. Also, one strange thing is I see environment variables for system predefined paths but the paths I define myself don't support environment variables? I can't use %ProgramFiles%. One has to use absolute paths or Program Files but .. works only if Program Files is on your system drive.

    [Did you remember to set the type to REG_EXPAND_SZ? -Raymond]
  13. Gabe says:

    The easiest way to start WordPad is to just run "write" — it even works from the command line or CreateProcess!

    This works because the Windows 3.x and earlier "word processor" was called Write.exe, so apps that displayed READMEs and such expected to be able to run WindowsWrite.exe (or the WindowsSystem32 version). When Win95 came around and replaced Write with WordPad, they made Write a stub that just invokes WordPad so as not to break everything that hardcoded one of those paths.

    It's so convenient (only 5 letters instead of 7) that to this day I only ever type "write" instead of "wordpad".

  14. Troll says:

    "Did you remember to set the type to REG_EXPAND_SZ"

    Oops yes of course! Thanks.

  15. Jim says:

    Oops, Gabe was actually saying something completely different, sorry!

  16. Jim says:

    Of course, if the comment software eats my comment, I don't need to apologise anyway. (I was apologising for posting a comment that misunderstood him slightly.)

    My comment was: App Paths were useful back on XP for running things quickly. I tended to use "winword" to run Word and "excel" to (duh) run Excel. They're pretty redundant now, for users at least, with the new start menu. I can just type "word" or even "wo" and Windows guesses the right shortcut.

  17. JamesNT says:

    Back in the MS-DOS days I was bitten myself a few times by issues with apps writing to autoexec.bat to add themselves to the path.  Games were infamaous for doing this.  The most common issue I had was paths that were to long.

    JamesNT

  18. Worf says:

    I think the reason CreateProcess() doesn't respect App Paths is becuase of the layering thing. CreateProcess, along with many others (Thread, File, etc) is a kernel level API call. You're aking the kernel to do the task directly, and the kernel has no idea about the fancy things everyone on top uses. It just loads a file and attempts to execute it through the loader.

    ShellExecuteEx though, uses the shell conventions, so it can launch documents and other non-executables by using the shell-specific registrations that map documents to applications, app paths, etc. Once it finds the proper command line, ShellExecuteEx passes the kernel a proper command via CreateProcess…

  19. ultramage says:

    Wow, thank you so much for this post! All these years I've been filling my PATH variable with packages like svn, php, perl, python, and cygwin – whose installation instructions are just "add directory to PATH". This will also help prevent dlls shipped with these apps from leaking everywhere.

  20. Alex Grigoriev says:

    Chuck Norris can solve the Halting Problem. He will halt the machine.

  21. about:blank says:

    The Run dialog needs a "Run as administrator privileges" checkbox to be useful to launch programs under Vista/7.

  22. AC says:

    I don't think you have to solve the HP. You already know that Windows is running, i.e. autoexec.bat did halt in some way. It would of course still be very much non-trivial and the wrong way to do things.

    (Although I'm not sure if I anger you by posting this. You seem to be irritated by YB posting OT side remarks, the nitpicker's corner might really upset you??)

    [You're assuming nobody has edited autoexec.bat since boot. (And that the user did not perform a Shift+F8 step-by-step boot.) -Raymond]
  23. Jim says:

    @about:blank :

    Unless you need a browse button, just use the search box in the start menu. Anything you type into Run will work there too (though it could potentially do something different, if there's a conflict). In fact even browsing for is faster there really (try typing "C:" and using the arrow keys). Plus it's one less keystroke to get there!

    The punchline is, if you didn't already know, running something from the search box by pressing shift+enter instead of just enter runs as admin.

  24. JamesNT says:

    @AC

    There are times when I think Mr. Chen does enjoy calling people out on some of the more "special" things they say.  However, there are times he is obviously irritated.  One never knows regarding one with the personality of a thermonuclear device.  :)

    JamesNT

  25. Gabe says:

    Jim: Do you mean Ctrl+Shift+Enter? Just Shift+Enter doesn't do anything different for me.

  26. Kelden says:

    Why is PowerShell set in the PATH then?

    On every new installation of Windows (7 tested), I have

    C:WindowsSystem32WindowsPowerShellv1.0

    in my PATH

  27. benjamin says:

    @Gabe: I do the same thing with pbrush. I still call MS Paint 'Paintbrush' anyway.

    Of course, I also still close windows by double-clicking the top left, so maybe I'm just set in my ways.

  28. Jim says:

    Gabe: Oops, you're right, thanks.

  29. Aaron says:

    What happens if I were to write my new super text editor and decide to call it WORDPAD.EXE and try to set its App Path?  Would registration fail or would it register but only ever find MS WORDPAD.EXE as it was registred first?

Comments are closed.