How to create and resolve a shortcut

This article presents 2 ready-to-use functions to create and resolve a shortcut.

Introduction

Shortcut is a file with an extension .lnk. Each of these files contain a special COM object that points to another file. Usually, when you try to open a .lnk file, the system opens a file which this shortcut points to.

Let's do the following experiment. Create a text file (file with an extension .txt) somewhere. Then create a shortcut pointing to this file (send me a private e-mail if you do not know how to create a shortcut manually). Then try to open the shortcut with Microsoft Word, using File->Open command and select just created shortcut. MS Word will do it correctly: it will open the text file that is pointed by this shortcut. Now do the same with Notepad. Instead of the text file content, you will see garbage. It means that Notepad has no idea how to deal with shortcuts.

So we came to a conclusion: in Windows a program should have a built-in support for shortcuts in order to handle them correctly.

In this article I will show how to do it. I will present 2 functions: how to create and resolve the shortcut. The code is well commented (in my opinion) and self-explanatory.

I am creating a shortcut on my machine and distributing it to several other machines.
The shortcut points to an executable on the local machine (Say C:\IE\IEinstall.exe).
Unfortunately the shortcut contains the UNC path to my machine. This creates problems when that path can be resolved from another machine but the logged on user on that machine does not have permissions for my machine (it may fail in other cases but this is definitely a case when it fails).

I would like to remove the UNC path information from my shortcut. There is a KB article about this:http://support.microsoft.com/default.aspx?scid=kb;en-us;150215
But I cannot find the tool mentioned in there in the resource kit.
Does anybody know where can I find that tool?
Or does anybody know the binary format of the shortcut so that I can remove the UNC by hand?

From my limited understanding of COM, I thought that you should call
pShellLink->Release();
in a couple of places to say that you had finished with the interface.
However, when I try this it causes compiler errors ???

Sorry to be dim but although your code is well-commented, I don't understand the principle of what it is doing. I tried to use this in a VC++6 app under ME -I added the headers#include <stdafx.h>#include <atlbase.h>#include <ShlObj.h>and it compiled and linked first time. However, it does not resolve a shortcut. Debug shows that the call hRes = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&ipShellLink); fails with hRes being returned 0x800401f0

Igor,
thanks - I tried to find that error message but failed. Since I am using VC6 I added the call CoInitialize(NULL) to InitInstance (there is no 'main' in a Windows program).

My app now works, although there is a minor feature - the lnk path that I pass uses forward slash to separate directories but ResolveShortcut returns backslash separated ones.

Also, Microsoft state that new applications should use CoInitializeEx, however I cannot get this to compile, using the header they specify...
see
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmf_a2c_36qt.asp

Thanks for the article
Unless it's because I haven't searched enough, I haven't found a command line shortcut creation tool for XP. This should do it.
If it works could I put the executable on my website?

I just tested it, a shortcut was created but it's target property was pointing to an non-existing folder (or file). It's an expected behaviour, since IShellLink has no way of knowing if a target exists or not.
But when it tries to resolve it then if it can not find a target it'll display a prompting dialog. To suppress the dialog box, you need to set the SLR_NO_UI flag.

How to obtain a correct path to an executed file for lnk-file of MSOffice 2002 (for example Microsoft Word.lnk in main menu or on Desktop).
I try it to make using IShellLink::GetPath.
I get a path like C:\WINDOWS\Installer\{91110419-6000-11D3-8CFE-0050048383C9}\wordicon.exe.
If to see this file in a binary mode, the file contains this information and the shortcut works correctly.

Yes, I used this function. The functions offered by you worked correctly for standard shortcuts.
But this function is not universal. In addition I use interface IShellLinkDataList for getting the extra information. Using IShellLinkDataList:GetFlag I obtain a flag with enabled bit SLDF_HAS_DARWINID (The link is a special Windows ® Installer link.) and disabled bit SLDF_HAS_LINK_INFO.

How to get information from the "special Windows ® Installer link"?
(Such shortcuts create many programs and including MSOffice)

Interesting...
Can you tell me what kind of shortcuts you are trying to resolve, i.e. MS Word document shortcut or MS Word exe shortcut?
I'll try to look into it, though can not promise anything (unfortunately I do not have much free time right now - too much going on at work).

So then I added the second attempt... the GetShortcutTarget() function and it works on MSI style links... but I have a link it doesn't work on... the "Program Compatibility Wizard" found under the "Accessories" sub menu. Any ideas?

I am focused on the IShellLinkDataList interface right now... seems like it is the right interface to get more data from but so far I have not been able to get any data blocks from it! I use ->GetFlags() and that works but when I call CopyDataBlock the pointer is always null no matter what SIG I use.

Does anyone know how to programmatically create a Desktop
icon (.lnk) to an app. in MSVC 2.0. I have searched everywhere: MSDN, the internet, all my lit. I can't believe
there's so little info on the most basic feature of Windows.
I would think there would be plenty of examples for MSVC 1.0
on up.

I'm just trying to find a way to do the same process of functions above, but now in C. However, I have found no resources at internet nor even in the microsoft documentation. Does anyone know how to make it?

I will not lie, I have never done it in C, I just do not understand why it can not be done. Link with the necessary dlls - that's all, right? I could be wrong, though.
May be you should ask this question in C++ forum.

Here is code to create a Desktop link using C.
In contray with C++ you have to use a pointer to the
Vtable in order to get to the IShellLink object.
Hope this helps.
I have a problem to use when I want to give a parameter
to the link object eg. I want to create a shortcut like
"C:\\MyPath\\AppName\\AppName.exe -Settings".
If you find out resolve please post....

Here is code to create a Desktop link using C.
In contray with C++ you have to use a pointer to the
Vtable in order to get to the IShellLink object.
Hope this helps.
I have a problem to use when I want to give a parameter
to the link object eg. I want to create a shortcut like
"C:\\MyPath\\AppName\\AppName.exe -Settings".
If you find out resolve please post....

John T wrote:I have a problem to use when I want to give a parameter
to the link object eg. I want to create a shortcut like
"C:\\MyPath\\AppName\\AppName.exe -Settings".
If you find out resolve please post....

I haven't tried it personally, but it looks like adding a call to SetArguments on the ShellLink object should work to add the "-Settings" argument.
psl->lpVtbl->SetArguments(psl, "-Settings");

Hi,
How can I create a shortcut to network connection, the broadband connection ?
Assume, use "rasphone.exe -a" to create a "broadband connection" in Network
Connections in WinXP.
Since network connection does not have file name, and it only has
CLSID.