December 19th, 2025
likemind blown3 reactions

A shortcut gives me a weird path for a program shortcut that doesn’t point to the executable, so what is it?

Say you have a shortcut file and you want to see what its target is. The natural thing to do is to call IShellLink::GetPath, which returns S_FALSE if the shortcut does not target a path, or returns S_OK and a path to the target. But for some shortcuts, it returns S_OK but produces a weird path to a file inside the C:\Windows\Installer directory that is definitely not the shortcut target. So what is it?

You’re seeing a backward compatibility consequence of shortcuts to MSI applications.

The Microsoft Windows Installer (MSI) was introduced in Windows 2000. It supports various types of installation functionality, but the interesting one here is install-on-demand. A shortcut to an MSI-installed application is not a shortcut to an executable, but rather it is a shortcut that encodes the MSI information to identify an MSI application. When the user double-clicks the shortcut, the shortcut file asks MSI to get the application ready to run, which involves installing the application and all its dependencies (if they aren’t already installed), and possibly verifying that the files are not corrupted and performing self-repair. Only after everything is ready to go does the shortcut actually launch the program. This install-on-demand behavior means that if the program hasn’t been installed, there is no target to execute.

The initial implementation of MSI shortcuts had the Get­Path method ask MSI for the application’s executable, and MSI would go off and say, “Hang on, I need to install it first,” and that might display some installation UI, possibly asking the user to reinsert the original install media if the package is not cached. We discovered during testing that lots of programs ask for the application’s executable path without any intent to launch the resulting application. As a result, you would find that your system would suddenly go bonkers installing every program on the Start menu just because some program wanted to enumerate the contents of the Start menu and get information about all of the shortcuts. These sorts of program are popular in managed environments where the system administrator wrote a tool to take an inventory of all the programs that have been installed across their organization. This also means that Get­Path can’t return S_FALSE to say “This does not refer to a file,” because those inventory programs insisted that they get a file path back so they can determine, say, how many of their users have CONTOSO.EXE installed.

The IShellLink::GetPath and IShellLink::Resolve methods were modified so that they didn’t actually give you the path to the executable (which would trigger an on-demand install) but rather gave you the path to a placeholder file.¹ This placeholder file usually had just enough information to keep most programs happy with what they found. The executable name matched that of the final program, like WINWORD.EXE, which tended to satisfy a lot of system inventory-type programs. And that placeholder also contained the icon for the final program, so that programs that tried to be fancy and show an icon for the program got the icon they wanted (even if not from the file they thought they were getting it from).

You can detect that you are being lied to by checking the shortcut flags returned by IShell­Link­Data­List::Get­Flags for the SLDF_HAS_DARWIN­ID flag. Darwin was the code name for what became the Microsoft Windows Installer.

Once you realize that you have an MSI shortcut, you can obtain more information about them by calling Msi­Get­Shortcut­Target, which will give you the MSI product code, feature ID, and component code that the shortcut refers to. You can pass the product code and component code to Msi­Get­Component­Path to get the path to the component if it is installed.²

If you are a real glutton for punishment, you can get the raw MSI descriptor by calling IShell­Link­Data­List::Copy­Data­Block and asking for the EXP_DARWIN_ID_SIG data block. The descriptor is returned in the EXP_DARWIN_LINK‘s szDarwinID and szwDarwinID members. What can you do with that descriptor? I have no idea, but you did ask for it.

¹ The Resolve method lets you override this by passing the SLR_INVOKE_MSI flag, which means “No really, I want you to install the shortcut target.” Use with extreme caution or you will be one of those programs that causes the user’s machine to go berzerk installing every program on the Start menu.

² Note that the component path is not the same as what the shortcut will launch when you double-click it. The shortcut includes command line arguments that the MSI package specified when it defined the shortcut.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

9 comments

Discussion is closed. Login to edit/delete existing comments.

Sort by :
  • stephen mitchem

    The advertised shortcut isn’t just for install on demand. If the program is already installed the shortcut will trigger a check for the files and reg keys that the application needs in order to run. Missing keys are extracted from the cached MSI on the PC, and files are copied from the source MSI. This can be used to install per-user files and keys when the application has been installed on a per-machine basis either by an admin or by Active Directory.

  • skSdnW

    CLSID_ShellLink’s IContextMenu will work without knowledge of the MSI specifics, that is the point of the placeholder. When it builds the menu for a shortcut to a .exe for example; it gets the target path and builds the menu with this information. In this case, .exe maps to the exefile progid and the verbs found there are added to the menu (merged with the lnkfile verbs).

    • GL

      For the CLSID_ShellLink implementation to return placeholder path on GetPath, it appears it must be programmed after MSI is conceived, because this behavior is likely designed after MSI is conceived. That’s why I would assume CLSID_ShellLink on 9x/NT4 (if not updated upon installing MSI) wouldn’t do anything special to MSI shortcuts, meaning that GetPath wouldn’t return the placeholder path.

      When building the context menu, a well-implemented IContextMenu should use ID list, which avoids the issue with GetPath hence doesn’t rely on placeholder paths being returned. Windows itself is likely to implement it well.

  • Jan RingoÅ¡ · Edited

    The whole concept of install-on-demand applications is a perfect case of “being so preoccupied with whether or not you could, and not stopping to think if you should.”

    Also, when is IShellLinkDataList finally gaining the uninstall registry subkey name, so that classic apps can be uninstalled/reconfigured from Start just like packaged apps?

  • skSdnW · Edited

    @GL Windows Installer was also available as a redistributable for 9x/NT4 (not sure if it supported on-demand shortcuts). I’m a bit rusty on the details but asking IShellFolder to build the menu for a .lnk will also incorporate verbs from the target with a combination of CMF_VERBSONLY and CMF_NOVERBS and this support is free even for pre-MSI shell if the placeholder has the same extension. This also applies to GIL_PERCLASS icon extraction (typically .txt .htm .bmp etc.).

    • GL

      CLSID_ShellLink isn't implemented by MSI, so it's unlikely there's any special treatment of MSI shortcuts in the implementation of CLSID_ShellLink in 9x/NT4. I'd imagine the following. Maybe the shell in 9x/NT4 didn't have an issue with MSI shortcuts even though it was programmed unaware of it. The shell could just have used GetIDList, and MSI targets on 9x/NT4 could have resided in a shell namespace extension added when MSI is installed. The context menu could have been built by the namespace extension's implementation, which would be MSI and it knew how to handle it. Otherwise, if 9x/NT4 shell had...

      Read more
  • skSdnW

    “This placeholder file usually had just enough information to keep most programs happy with what they found.” and the file extension is important for the shell so the context menu can build the static verbs for the correct target.

    • GL · Edited

      I’d imagine the shell (‘s composite IContexMenu) is well aware of MSI shortcuts and wouldn’t need the placeholder file.

      (Preemptive annotation — in reply to skSdnW)