A customer question about shortcuts that don’t have a target path

A customer had a question about the Minesweeper shortcut on Windows 7:

We found something strange when we tried to retrieve target path information from the Minesweeper shortcut, specifically, the system built-in shortcut for Minesweeper application which is normally found in C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Games\Minesweeper.lnk. When we tried to view the property of this shortcut file, we got the information below:

Target type: Minesweeper
Target location: Games
Target: Minesweeper

On the other hand, if we manually create a shortcut to Minesweeper, the shortcut properties say

Target type: Application
Target location: Minesweeper
"C:\Program Files\Microsoft Games\Minesweeper\Minesweeper.exe"

We are unable to obtain the target path from the system built-in shortcut, but we can get it from the one we created manually.

Can you explain the difference between the two shortcuts? How can we get the target path from both types of shortcuts?

As we saw some time ago, a shortcut can point to anything in the shell namespace, and the target path is meaningful only for shortcuts whose targets are, y'know, paths. if the target of the shortcut is not a file system object, then you can't get a path to it because those virtual objects don't have paths.

But it wasn't clear why the customer is trying to take these shortcuts apart. I asked, "Why is the customer obtaining the target path? Is this for some sort of software inventory tool?"

The customer liaison explained:

This is an issue raised by my customer. The customer is retrieving the target path of a shortcut by using IShell­Link::Get­Path(), but they are unable to get the target path information from some shortcuts, of which Minesweeper.lnk is just an example. The customer wants to retrieve the path information for arbitrary shortcuts including those which point to third-party applications. I don't understand how the underlying mechanism works, so I don't know whether there is a workaround that would allow the customer to retrieve the path information from shortcuts like Minesweeper.lnk. Is there some other way to retrieve the target path information?

The customer liaison gave a long response that didn't actually answer the question.

With some prodding, we got an answer from the custom liaison: The customer is a laptop manufacturer, and their laptop keyboard has some dedicated function keys. They are writing software that lets the user assign shortcuts to those function keys, so that when the user presses the function key, the corresponding app launches. They want to get the target path of the shortcut so they know what program to launch.

Y'know, if all you want to do is launch the thing that a shortcut refers to, you can just launch the shortcut.

ShellExecute(hwnd, nullptr, "Minesweeper.lnk",
             nullptr, nullptr, SW_SHOWNORMAL);

This has the advantage of also respecting the command line arguments, the current directory, the hotkey, any application compatibility settings, console settings (if the target is a console application), and all the other information stored in the shortcut. It also means that if the target of the shortcut gets moved or renamed, the standard shortcut resolution code will kick in and try to find the target, wherever it ended up.

This is like designing an overhead console in an automobile for a garage door opener. One way to do it is to have the user bring the garage door opener to the car, and press a button that causes the car to take apart the garage door opener and analyze it to figure out the transmission frequency, extract the rolling code, and whatever other information you need in order to perfectly replicate the operation of the garage door opener.

Or you could design the overhead console so it had a compartment where the user can place the garage door opener, and when they want to open the garage door, they push the button.

The customer liaison replied that the customer accepted the workaround of calling Shell­Execute and it is working fine.

I didn't bother pointing out that calling Shell­Execute isn't the workaround. It's actually the standard technique. The thing about extracting the target path and manually executing the program: That is the thing that smells like a workaround.

Comments (38)
  1. Mason Wheeler says:

    This article actually feels like exactly what you accused the customer liaison of providing: “a long response that didn’t actually answer the question.”

    I can understand how the answer that “a shortcut can point to anything in the shell namespace” can make sense in the context of things that aren’t files, but let’s be honest: most things you use shortcuts to are real files that exist at a real point in the file system. Many, many times, I’ve been frustrated by a shortcut to a real file that refuses to tell me where that file is located because, for one reason or another, I want to find the file behind the shortcut.

    How do I do this?

    1. Pierre B. says:

      Shortcut are a generic way to refer to some information. Some of these are file, other are not, so there would be nothing for you to retrieve.

      AFAIK, you can create new types of shortcut and provide a custom handler. For example, you could create a shortcut that links to an event in the event viewer. There is no path to that. Another example is Steam. It creates shortcut with a special steam “URL” that lauches the game. (In that case, yes, there is path behind it, but the OS cannot know what mapping there is betwen the link and the game. That is internal to Steam. There would need to be a standardize way for the OS to ask handlers for such info. And maybe there is, but as I said, there may not be a a real file behind the link.)

    2. Mark (The other Mark) says:

      Well, sometimes they are more than just shortcuts to files. For example, Advertised shortcuts point to the MSI typically located in C:\Windows\Installer (I’m sure that’s an implementation detail), and the actual file level target, if any, would be in the shortcuts table. This allows self-healing of products, and install on demand- the file the shortcut points to might not even exist until after you click on it.

      The point is, thinking that shortcuts always point to files, or even if they do eventually point to files, that it’s directly pointing to them, isn’t correct. So any approach based on that assumption should be re-thought, or you’ll have to handle a bunch of edge-cases.

    3. I didn’t answer the question. I solved the problem. (The answer to the question is actually in the article: Shortcuts to virtual objects don’t have paths. Because that’s what “virtual” means.)

      1. ZöBook says:

        But Minesweeper is not a virtual object, is an application. Is this useful in this case in any way? I mean, making the shortcut “special” and not a regular shortcut pointing to an executable file.

        1. In this case, it is a virtual object: It’s a virtual “game” object in the Games folder that contains information like the ESRB rating, as well as the path to the primary executable.

      2. IanG says:

        This has left me wanting to know how the minesweeper shell target actually works. Presumably there is an actual executable somewhere – what’s the reason for using a virtual object rather than a plain old path to the executable?

        1. IanG says:

          Whoops, never mind, you already answered that in another reply. Sorry!

  2. Karellen says:

    I’m guessing that the customer’s mental model of ShellExecute() as applied to shortcuts is wonky.

    ShellExecute() runs (executes) a program. If you give it an executable, it runs the executable. If you give it a document, it finds the program that handles that type of document, and runs that program with that document. So, what happens if you give it a shortcut? My guess is that the customer’s mental model is that shortcuts aren’t executables (correct). Therefore, ShellExecute() runs a program which knows how to handle shortcuts (incorrect), and that program (let’s call it ‘X’) ends up running the program they actually want to run (minesweeper).

    The customer is examining their model of ShellExecute() and thinking “Too many layers!. Why run X whose only job is to run minesweeper? We should just run minesweeper directly ourselves. If we can figure out the API calls that X uses to unpack the shortcut and run minesweeper, we can save a needless CreateProcess(), and avoid the “workaround” of running a program to run our program.”

    Not realising that ShellExecute() is the API call that does all of this in-process.

  3. Kevin Fee says:

    Okay then. Let’s say I want to go to the folder in which Microsoft Excel is installed because something is broken and won’t launch so I need to go to the directory (which may be in a non-standard place, and even if it isn’t, is it under Program Files or Program Files (x86)? Because Office is in both.) to do whatever. How do I find the directory? The usual way is to go to my start menu, right click on the shortcut, click properties, and look at the target path. But because Microsoft is special, Excel goes the non-standard route of creating a shell “virtual object” for their executable and so I can’t find the path.
    I can understand a shortcut to Control Panel not having a path. It’s part of the system. But a shortcut to an actual application, like Minesweeper, Calculator, Notepad, Word, Excel, etc. with an actual executable path? Why is that a virtual object? What’s the benefit? The only “benefit” I see is hiding the path, which is a very user hostile feature.

    1. That shortcut to Excel is really a pointer to an entry in the MSI database. The files that are used by Excel are not all in one folder, and the MSI database keeps track of where they all are. To repair Excel, you go to the “Programs and Features” folder, click Excel, and then click “Repair”.

      1. Kevin Fee says:

        I wish I could have edited my post, because as soon as I clicked the “post comment” button I remembered where I really needed to know the path to Excel: I need to tell Visual Studio or another program that I want to open CSV files, etc, with Microsoft Excel. None of these programs (including Microsoft Visual Studio) support shell “virtual objects”, they ask for a path. For example, in Microsoft Visual Studio 2013, putting in the .lnk from the start menu says “Cannot open file {path to .lnk}.”. So how do I find the path to Excel?

        1. guest says:

          By running Excel and looking under Task Manager for the path to the exe?
          Of course that assumes the exe does what you want, i.e. takes a command line parameter and loads the file that you specify. Not all programs are that simple, which is kind of the point of having virtual objects.
          VS not supporting it is a limitation of VS. What you are asking for is a workaround for that limitation. It’s not because shortcuts are “user hostile”.

        2. Erik F says:

          The program might not even be installed yet! If an administrator pushes a MSI package onto your computer, the package might be set to do a demand install, so asking for a program path on a shortcut would return “???” until the program was installed.

      2. alegr1 says:

        One shortcoming of those managed shortcuts is that they don’t accept dropped files. At least that was my experience a while ago.

        1. Neil says:

          I can’t run them as another user either. (A certain corporate anti-virus UI needs to be run as a specific domain administrator account, so if you’re a local administrator you can’t use Run as Administrator on the managed shortcut. Also, things are even worse on Windows 10, since I can’t readily get at the shortcut properties anyway.)

  4. DWalker says:

    I think the shortcuts that point to “virtual objects” are interesting. I know that Microsoft Office sometimes creates shortcuts for Word, Excel, etc. that look like this.

    I wondered how they worked, but I certainly wouldn’t try to take them apart. Yes, executing the shortcut is the right way to, um, execute the shortcut.

    If I get motivated, I’ll look around and figure out what a “virtual object” is. There’s already a link in this article!

  5. IanBoyd says:

    I right-click Minesweeper in the Start Menu, and select Send To -> My Favorite Resource Hex Hacker Editor. Rather than opening “C:\Program Files\Microsoft Games\minesweeper\minesweeper.exe”, it opens a Windows .lnk file. As a workaround, i can instead right-click the shortcut, select Properties, and copy-paste the shortcut target. Nope. As a workaround, i can run the program, and then use Process Explorer to copy-paste the path of the running program.

    One virtue of answering the question, rather than solving the problem, is that the answer is applicable in the future, and to other people – something i point out when i ask a question on Stack Overflow. The ideal question contains a contrived concrete example of a hypothetical situation.

  6. pm100 says:

    can you please explain why the minesweeper shortcut is not a ‘classic’ shortcut pointing at the binary. Having a link to object ‘Minesweeper’ suggests that somewhere else there is something that knows ‘Minesweeper’ means ‘that binary over there’ (another CS problem solved by one more level of indirection?)

    1. Yup, it’s a pointer into the “Games Database” which has stuff like the ESRB rating, game category (“action”, “card game”, etc.), support links, locations where the saved games are kept, and a bunch of other stuff.

  7. comment that apparently will never show because of broken moderation here says:

    @IanBoyd: Surely as you must know by reading through the blog post, the point is that not every shortcut points to something that has a path. So the literal answer to the question is “you can’t”. Rather than just leaving things at that, Raymond is doing the customer a service by actually trying to understand and solve their problem.

    Surely it is not that hard to grasp the concept that sometimes a question is simply the wrong question to ask? Besides, it’s ridiculous to compare Stack Overflow to customer support. There is not really any “other people” to speak of in Raymond’s customer support scenario. This article in this blog you are reading is effectively doing exactly what you are proposing, “answering the question” (by explaining why it’s not the right question in the first place) to a larger audience.

    @pm100: see the article Raymond linked to. Specifically: “Similarly, the entries in the Games Folder are not executables; they are entries in the games database.”

    1. (The moderation rules are that the first comment from any user is auto-moderated. I manually approve them, at which point future comments are auto-approved. By far the most common reason for rejection is that you used a fake email address.)

      1. Mason Wheeler says:

        > By far the most common reason for rejection is that you used a fake email address.

        Interesting. Why is this cause for rejection? Do you frequently have a need to email commenters?

        1. Nope. It just provides accountability.

        2. Brian_EE says:

          He adds them to the mailing list for his fan club.

          1. Nick says:

            Your ideas are intriguing to me and I wish to subscribe to your newsletter.

          2. Ray Koopa says:

            There is a fan club? Where to sign up? I still have an unsigned copy of his book here, waiting for an autograph!

      2. Ivan K says:

        Off topic, but I noticed that email addresses sometimes show up as user names for comments on archived articles. Possibly due to the blog migration. For example, the link to the old ‘discardable’ discussion yesterday (https://blogs.msdn.microsoft.com/oldnewthing/20120712-00/?p=7143) has a bunch of ‘Anonymous’ posters, some MSDN user names, and some email addresses. Replies to some of the email address -named commenters use the @user format which indicates to me that the commenter didn’t orginally use his/her email address when making the post, because otherwise the person who replied wouldn’t know to say (for example) ‘@person’, because ‘something-similar-to-person@domain.com’ is now shown as the commenter’s name.

  8. Obi says:

    Just executing shortcut isn’t really the solution because shortcut can be deleted but user might still want to launch app from dedicated key. Though, looking for shortcuts and extracting executable paths from them also isn’t solution to question “which apps are installed on this pc and what might user want to run”. So, bad idea generating more bad ideas.

  9. Richard says:

    Is there such a thing as a “relative” shortcut?

    I often have a need to send early-alpha executables to testers and product management that require appropriate command-line parameters to run.

    I originally tried including a .lnk file, however this contains absolute paths and so doesn’t work on their machines.

    At the moment I include a set of .bat files that call the main executable with those parameters, but this is messy as it produces a CMD window etc.
    The testers don’t care, but the product managers often get hung up on “Why does an ugly black box flash up?”, distracting them from looking at the application itself.

    It would be much nicer if I could could send them a lnk that actually worked.

    Obviously I could write an installer for all this, however that’s a fair bit of work for very early in a project.

  10. jimbo1qaz says:

    1I feel that Virtual shortcuts are a bad idea. Shortcuts should be a view to a program, and not act as programs themselves.

    – Do you use shortcuts to a GUID? Then is the GUID used as the path? … no, you mentioned “don’t try to get the path, use the shortcut”.
    – Anvil Studio uses virtual shortcuts. They break every time I install a different version, even when maintaining the same path. This may be their fault. But still, file paths are transparent, editable, and Just Work.
    – On Windows 10, Office trial shortcuts are readable and editable. Are they non-virtual shortcuts? Do you just replace the shortcuts whenever Word is moved? Do you do some special magic to maintain file associations?

    # Uniqueness (canonical? authoritative?)

    Let’s say there are shortcuts on the desktop, start menu, and sometimes the Startup folder. Which one should be called when you want to execute the program?

    [b]What if someone deletes their desktop/start shortcut, and suddenly the hotkey can’t find the program?[/b]

    # File Associations

    – Manually added file associations link to EXE files. What about automated ones?
    – I manually browsed to the Anvil Studio virtual shortcut in the start menu… I get the excellent popup, “This app cannot be run on your PC”.

    Why does Anvil Studio (or anything for that matter) use virtual shortcuts, if the file path works well enough for file associations?

    # Transparency (arguments, program folder, etc.)

    What if I want to call the actual EXE over cmd (is Powershell the cool new thing now?) and pass arguments? Or add the folder to my PATH? Or create a symlink or batch file alias in my personal PATH folder?

    What if I want to look at the actual EXE (say for file associations), look for uninstallers, or edit files? (Is that even possible with Click-To-Play, which I’ve encountered once or twice across many years?)

    I’m struggling to see how shortcuts to a game database entry is a good idea. It’s an opaque entity that doesn’t act quite like a folder, but points to real filesystem paths.

    # Linux

    On the Linux side of things, symlinks point to specific paths, are fully transparent, respect command-line arguments, etc. But they aren’t used as Start Menu shortcuts.

    Desktop files are a humongous mess though, in my opinion. Windows got program associations right (aside from not being able to use .py scripts as openers).

  11. Jonathan Gilbert says:

    How does one go about getting a Customer Liaison to whom such questions may be posed in the first place? I have some questions of my own about shortcut files, and I don’t know how to get them to people who have the technical knowledge to answer. :-)

    1. You pay money to Microsoft for a professional support contract that gives you access to them, or you pay for a single incident.

      An MSDN Pro subscription includes two support incidents a year, iirc.

      1. MarcK4096 says:

        I’ve never been able to get this level of support from incident support. That generally gets you a level 1 offshore support analyst. I think paying big money for the support contract is the way your questions make it to people of Raymond’s caliber.

        1. Peter says:

          msdn “support” is a joke. It’s a stone wall that only “answers” with questions and ask you to perform useless tasks, like rebooting until stuff works.

      2. Brian says:

        Look up Microsoft Premier Support on the support.microsoft.com web site. It ain’t cheap, but you get a person whose job it is to keep you happy (for some definition of happy). Premier support customers are Microsoft’s happiest customers (http://www.crmbuyer.com/story/31853.html).
        You won’t get that level of support from any of the other, cheaper support options.

  12. jgh says:

    It’s the “I don’t keep my socks in your top drawer” problem.

    You may keep your socks in your top drawer. I don’t keep my socks in any of your drawers, and I don’t keep my socks in my top drawer. I may not even keep my socks in a drawer at all. Hardwaring into socks_fetch() a call to drawer_open(_TOP) may work for your socks but will not work for my socks, and even trying to write a drawer_searchfor(_SOCKS) function will also fail. You should alwas do what the user using the program specifies, socks_fetch() { location=config_rd(USER, _SOCKS); …etc.

    I’ve lost count of the number of broken programs that look for my socks in the author’s top drawer.

Comments are closed.

Skip to main content