Hi! It looks like you're new here. Welcome! If you like what you see, I encourage you to subscribe to my RSS feed. If you're worried about adding another RSS feed that will add to your information overload, don't! I'm not a prolific poster. Thanks for visiting!
This is a problem that’s been bugging me for about a year and I finally found time to dig in and work on how to solve it. A big thank you goes to Aaron Stebner for pointing me in the right direction. Thanks Aaron!
Anyway, for various reasons I’ve wanted to display a list of applications the user has installed on the computer. Getting at the All Programs folder in the Start Menu is not too big a problem. You can get parts of it via Environment.GetFolderPath(SpecialFolder.Programs) and other parts of it (for all users) via a bunch of P/Invoke incantations that I’m not going into here. Iterating through all subfolders and picking out the .lnk files is not a problem either.
What is a problem (at least it was for me) is what to do with those .lnk files that you can’t get parsed correctly via WshShell.CreateShortcutFile() after adding a reference to the Windows Script Host Object Model to your project. The .TargetPath will usually return something down in a C:\Windows\Installer\{GUID} directory.
I had noticed that the Windows Installer XML 3.0 project creates shortcuts like that, and since Aaron is involved in that project, I asked him about it. He graciously told me that those shortcuts are “advertised” shortcuts, a kind of Windows Installer shortcut that enables putting a link in the Start Menu (or elsewhere) while not necessarily installing the whole product that the link points to. So I started digging in with Google. A CodeProject article contained a comment about two functions that can be used in combination to find the real target of and advertised shortcut: MsiGetShortcutTarget() and MsiGetComponentPath(). After some more digging, I had P/Invoke declarations for both of these from this SourceForge project.
I ended up with this bit of code, which I use first on any shortcut file I need to interpret; then if it returns null, I use the WshShell way instead.
public static string ParseShortcut(string file) { StringBuilder product = new StringBuilder(MaxGuidLength + 1); StringBuilder feature = new StringBuilder(MaxFeatureLength + 1); StringBuilder component = new StringBuilder(MaxGuidLength + 1); MsiGetShortcutTarget(file, product, feature, component); int pathLength = MaxPathLength; StringBuilder path = new StringBuilder(pathLength); InstallState installState = MsiGetComponentPath( product.ToString(), component.ToString(), path, ref pathLength); if (installState == InstallState.Local) { return path.ToString(); } else { return null; } }
If you’re interested, you can download the class with the rest of the needed declarations.
Categories: Software development

7 Responses to “How to parse "special" .lnk files, aka. MSI shortcuts aka. Windows Installer advertised shortcuts using C#”
[...] sure to drop by his site and grab the rest of the sample code just incase you need more info - even if it is done in [...]
This was incredibly helpful to me. Thank you for taking the time to publish this explanation and example on the web. I have been trying to figure out how to parse advertised shortcuts for many hours, and this was just the ticket. thanks!
Glad to be of help. And thanks for taking the time to comment as well!
Have you ever gotten this code to work on Vista? The MsiGetShortcutTarget() method is returning nothing for advertised shortcuts on my Vista Business OS.
I’ve got it to work on Vista Home Premium and Ultimate. Maybe in your case the shortcuts are for things that are truly advertised and not installed yet, i.e. there is no real target at the time you try to resolve the link? Also, I apply the WshShell method after MsiGetShortcutTarget() returns null (note I didn’t include that code in the downloadable sample). I assume you are doing that too?
Thanks for responding! I am, in fact, using the WshShell method after the MsiGetShorcutTarget() returns null from parsing a .lnk file, and it works like a champ. However, it’s weird. It’s the MS Office 2003 advertising shortcuts that are returning null in my case, and I know they’re installed as I use them daily. The weird part is that the return value fromMsiGetShortcutTarget() call is 1603, which is ERROR_INSTALL_FAILED. The WshShell method returns the icon file for these links. Not sure what’s going on here, but I’m going to try it on some other advertising links that I know I have. Thanks for responding and letting me know that it’s not a fundamental Vista issue!
No problem. I haven’t seen problems with MS Office 2003 shortcuts myself, but I have seen Office 2007 shortcuts work. Maybe it depends on the install source (admin share, SMS, etc.)?
Care to comment?