The Wayback Machine - https://web.archive.org/web/20130720213217/http://www.codeguru.com/cpp/com-tech/shell/article.php/c1327/Creating-File-Links.htm

Creating File Links

For a new Project I needed the function, to create Links to a File (in Startmenu and Autostart). But that is the Point to take a look on the MFC-Classes. But there is not so many Info about. The Old-Version (for Win 3.11) with DDE was nice and runs fine. But that is not the way to write it under WinNT 4.0.

Okay, the right book at the right time, and every problem can be solved...

The Solution I found under a small chapter about IShellLink. But not much Info, and so i tried it out.

At First is the boring COM -
	CoInitialize(NULL);	
	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
	IID_IShellLink, (LPVOID*) &psl;);

If it was successful, you can set Path, Description and so on. But to create the link in real (on Harddisk) we need IPersistFile

	hres = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf;);

and save the File...

	hres = ppf->Save(, TRUE);

Thats all.

So, if anybody need it complete:

// Creating a Link with IShellLink
// strPathObj  = Object with Path
// strPathLink = Path where the Link will appear
// strDesc = Link-Decription (the text under the Icon)
// CoInitialize(NULL) wird vorausgesetzt !!

HRESULT MyMainClass::CreateLink(const CString strPathObj,const CString
strPathLink, const CString strDesc)
{
HRESULT hres;
IShellLink* psl;

	CString strMyPath = strPathLink;

	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID*) &psl;);
	if (SUCCEEDED(hres))
	{
		IPersistFile* ppf;

		psl->SetPath(strPathObj);
		psl->SetDescription(strDesc);

		hres = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf;);

		if (SUCCEEDED(hres))
		{
			strMyPath += ".lnk";  // Important !!!

			WORD wsz[MAX_PATH];
			MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strMyPath, -1, wsz,
MAX_PATH);

			hres = ppf->Save(wsz, TRUE);
			if (hres != S_OK )
				MessageBox(NULL, "IPersistFile->Save() Error", "Error", MB_OK);
			
			ppf->Release();
		}
		psl->Release();
	}
	return hres;
}
Okay, lets take a look on the Function above : What you need to make the link is only to know where is the File for the Link, where you want to create the Link, and what a Name should appear under the Icon. The Path where comes in the Link must be added with the Name for the Link ( under the Icon) and needs (its Important) a .lnk extension.
C:\\.lnk

Now call the Function :
FileLink([Source-Path with File],
	 [Destination-Path with an allowed Name and .lnk as Extension] 
         (like C:\[Path]\[Name you want].lnk ]);

And if you would like to try a complete Sample you can download FileLinkDemo.zip (only Win NT4.0 tested) (19KB)

Date Posted: 10/5/98

IT Offers

Comments

  • Creating PIF's

    Posted by Legacy on 10/16/2000 12:00am

    Originally posted by: Amnon

    Hi, Michael.
    Thank you very much for your article about creating links.
    We need in our project create PIF's along with links. Is the're a way to do it ?
    Amnon

    Reply
  • Library problem

    Posted by Legacy on 10/05/2000 12:00am

    Originally posted by: Jesper Mattsson

    I get "unresolved external symbol" on CoInitzialize() and CoCreateInstance() from the linker.

    How do i make it find the right library?

    Reply
  • Problems with handles! -> Memory overflow!

    Posted by Legacy on 03/29/2000 12:00am

    Originally posted by: Michael D.

    I have encountered a problem in my coding concerning the creation of shortcuts using the given code. As i'm creating shortcuts from time to time on the desktop and in a folder during runtime of my source (NT-Service), i have discovered that the command
    CoCreateInstance(...) and
    psl->SetPath(Target)
    envoke 3 handles in total.
    Since my code is a service, which runs for days - not to mention weeks or months, i get a momory overflow due to tons of handles which my service produces.

    Does someone know any solution to my problem or can give me a hint? I'd appriciate any help!

    Thanks in advance

    Michael

    Reply
  • How to indicate position on the desktop when creating a shortcut!

    Posted by Legacy on 03/26/2000 12:00am

    Originally posted by: Eric Forget

    The code work properly but can i indicate the position of the new shortcut when i created it on the desktop?

    Eric

    Reply
  • creating internet shortcut

    Posted by Legacy on 12/22/1999 12:00am

    Originally posted by: Venu Vemula

    Creating internet shortcut is little different than the general shortcut,
    
    so here is the code for Internet shortcut creation

    //Arguments
    pszURL - url location e.g 'http://www.sample.com/index/html'

    pszURLFileName - shortcut filename, should have extension of .url otherwise does not work. e.g "C:\test.url"
    LPCSTR szDescription - description of the shortcut
    LPCTSTR szIconFile ; icon file(could any .exe ot .dll)
    int index; index of the icon resource in above .exe or .dll

    HRESULT CreateInterShortcut (LPCSTR pszURL, LPCSTR pszURLfilename, LPCSTR szDescription,LPCTSTR szIconFile = NULL,int nIndex = -1)
    {
    HRESULT hres;


    CoInitialize(NULL);

    IUniformResourceLocator *pHook;

    hres = CoCreateInstance (CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
    IID_IUniformResourceLocator, (void **)&pHook;);
    if (SUCCEEDED (hres))
    {
    IPersistFile *ppf;
    IShellLink *psl;

    // Query IShellLink for the IPersistFile interface for
    hres = pHook->QueryInterface (IID_IPersistFile, (void **)&ppf;);
    hres = pHook->QueryInterface (IID_IShellLink, (void **)&psl;);
    if (SUCCEEDED (hres))
    {
    WORD wsz [MAX_PATH]; // buffer for Unicode string

    // Set the path to the shortcut target.
    pHook->SetURL(pszURL,0);

    hres = psl->SetIconLocation(szIconFile,nIndex);

    if (SUCCEEDED (hres)) {

    // Set the description of the shortcut.
    hres = psl->SetDescription (szDescription);

    if (SUCCEEDED (hres)) {

    // Ensure that the string consists of ANSI characters.
    MultiByteToWideChar (CP_ACP, 0, pszURLfilename, -1, wsz, MAX_PATH);

    // Save the shortcut via the IPersistFile::Save member function.
    hres = ppf->Save (wsz, TRUE);
    }

    }

    // Release the pointer to IPersistFile.
    ppf->Release ();
    psl->Release ();
    }
    // Release the pointer to IShellLink.
    pHook->Release ();
    }
    return hres;
    }

    Reply
  • easy way to setting up a icon for shortcut

    Posted by Legacy on 12/18/1999 12:00am

    Originally posted by: Marcos Mori de Siqueira

    It's simple.
    
    

    .
    .
    .
    hres = ppf->Save(wsz, TRUE);
    ppf->Release();
    }
    //-----------------------------------------------------
    // just add this line
    psl->SetIconLocation(Target, 0);

    // where: Target is the .exe file
    // 0 - Icon index inside .exe
    //-----------------------------------------------------
    psl->Release();
    }
    }
    return hres;
    }


    Reply
  • How can application get multifiles at the same time?

    Posted by Legacy on 12/17/1999 12:00am

    Originally posted by: HenryIII

    HI,men
    Could I ask you some qestions about VC++ programing?
    In fact, I wanna get the work out that when draging
    some files to my application, it can get these filenames
    into string buffers. I know Winamp(MP3 player) can do
    this. For examples, when you choose a lot of mp3 files
    and press "ENTER", winamp will play them one by one
    ( Of course *.MP3 file should open with winamp )
    Apparently, winamp get all of them. But some application
    can get only one object file.
    How can I do it?
    Looking forward your suggestion.

    Reply
  • I want to launch application as file is double clicked..!

    Posted by Legacy on 07/08/1999 12:00am

    Originally posted by: maroo

    I want to launch application as file is double clicked
    in window explorer(not browser).

    How to make it??

    Reply
  • Notes and Enhancements : CreateShortcut

    Posted by Legacy on 11/17/1998 12:00am

    Originally posted by: Firo

    Some things I noticed about this method:
    
    

    - The SetDescription() call doesn't work. The link created always
    takes as description the name of the file (without the .lnk).
    Hence I omitted the description part.
    - The code doesn't check if the filename already has a .lnk in it
    and appends .lnk all the time. I fixed that.
    - The variable names are not too self-explanatory, so I took the
    liberty in renaming them.
    - There is no way to pass arguments to the target application. I fixed
    that.

    Additions/Changes

    - I defaulted the path to the Desktop. Most of the time, users want
    to create a link on their desktop or in a folder on their desktop.
    Now the user only has to supply the link name (which also will be
    the link description). It should be no hassle removing that piece
    of code and passing a whole path if needed.
    - I added an "Arguments" string that contains the arguments you want
    to pass to the target application.
    - I added a 'bool IsFolder' defaulted to FALSE which allows the
    creation of a folder. The Target and Arguments are ignored when
    this flag is set.

    Examples of usage:

    CreateShortcut("explorer.exe", "c:\\temp", "Open The Temp Directory");
    * Creates a shortcut on the desktop that runs "explorer.exe c:\temp"

    CreateShortcut("", "", "Desktop Folder", TRUE);
    * Creates a 'Desktop Folder' folder on the desktop

    CreateShortcut("notepad.exe", "c:\\temp\\file.txt", "Desktop Folder\\Edit the
    File");
    * Creates a shortcut IN 'Desktop Folder' on the desktop that runs "notepad.exe
    c:\temp\file.txt"


    The modified code:

    #include "direct.h" // This is needed for _mkdir


    //In the .h file
    HRESULT CreateShortcut(const CString Target, const CString Arguments, const CString LinkFileName, bool
    IsFolder = FALSE);

    //In the .cpp file
    HRESULT CreateShortcut(const CString Target, const CString Arguments, const CString
    LinkFileName, bool IsFolder)
    {
    HRESULT hres;

    CString Desktop=getenv("USERPROFILE"); //Get the path to the desktop
    Desktop += "\\Desktop\\";
    CString Link = Desktop + LinkFileName;

    if (!IsFolder)
    {
    IShellLink* psl;
    hres = CoCreateInstance(CLSID_ShellLink,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_IShellLink,
    (LPVOID*) &psl);
    if (SUCCEEDED(hres))
    {
    IPersistFile* ppf;

    psl->SetPath(Target);
    psl->SetArguments(Arguments);

    hres = psl->QueryInterface( IID_IPersistFile,
    (LPVOID *) &ppf);

    if (SUCCEEDED(hres))
    {
    CString Temp = Link;
    Temp.MakeLower();
    if (Temp.Find(".lnk")==-1) //Append if .lnk doesn't exist yet
    Link += ".lnk";
    WORD wsz[MAX_PATH];
    MultiByteToWideChar(CP_ACP,
    MB_PRECOMPOSED,
    Link,
    -1,
    wsz,
    MAX_PATH);

    hres = ppf->Save(wsz, TRUE);
    ppf->Release();
    }
    psl->Release();
    }
    }
    else
    hres = _mkdir(Link); //Create the folder on the desktop

    return hres;
    }


    Enjoy!

    Firo
    Software Engineer
    AutoCAD Engineering
    Autodesk, Inc.

    Reply

Go Deeper

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds