C++ problem to resolve .lnk files with IShellLink:GetPath()

Posted on 2008-11-15
Last Modified: 2012-05-05

I use the IShellLink:GetPath() method to resolve .lnk files.

It works fine with the most of my .lnk files (like TuneUp, NotePad, and all Windows programs)

But, with programs like Safari or Adobe Reader, the method just returns this :

C:/Windows/Installer/{xxxxxxxx}/SafariIco.exe for Safari


C:/Windows/Installer/{yyyyyyyy}/SC_Reader.exe for Adobe Reader

How can I get the real path of theses .lnk files WITH DEV-CPP ?

My actual code is attached.

Thanks you in advance !
#include <windows.h>

#include <objidl.h>   /* For IPersistFile */

#include <shlobj.h>   /* For IShellLink */

#if defined(_MSC_VER)

#pragma comment(lib, "ole32.lib")

#pragma comment(lib, "uuid.lib")


#include <stdio.h>

#include <tchar.h>

BOOL GetShortcutTarget(LPCTSTR szShortcutFile, LPTSTR szTarget, SIZE_T cchTarget)


    IShellLink*    psl     = NULL;

    IPersistFile*  ppf     = NULL;

    BOOL           bResult = FALSE;

    if (FAILED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl) ))

        goto cleanup;

    if (FAILED( psl->QueryInterface(IID_IPersistFile, (void **) &ppf) ))

        goto cleanup;

#   if !defined(UNICODE)

        WCHAR wsz[MAX_PATH];

        if (0 == MultiByteToWideChar(CP_ACP, 0, szShortcutFile, -1, wsz, MAX_PATH) )

            goto cleanup;

#   else

        LPCWSTR wsz = szShortcutFile;

#   endif

    if (FAILED( ppf->Load(wsz, STGM_READ) ))

        goto cleanup;

    if (NOERROR != psl->GetPath(szTarget, cchTarget, NULL, 0) )

        goto cleanup;


    bResult = TRUE;


    if (ppf) ppf->Release();

    if (psl) psl->Release();

    if (!bResult && cchTarget != 0) szTarget[0] = TEXT('\0');

    return bResult;


int main(void)


    TCHAR szTarget[MAX_PATH];




         szTarget, MAX_PATH);

    _tprintf(TEXT("The shortcut target is '%s'.\n"), szTarget);



    return 0;


Open in new window

Question by:Valty
    LVL 86

    Expert Comment

    Um, I assume the "{xxxxxxxx}" part is actually a GUID - then these *are* the real file names, check them out. E.g. a short excerpt from my Windows\Installer directory:
    04.02.2008  05:11    <DIR>          {AC76BA86-7AD7-5464-3428-800000000003}
    05.05.2008  05:40    <DIR>          {C04E32E0-0416-434D-AFB9-6969D703A9EF}
    04.08.2007  10:37    <DIR>          {CE386A4E-D0DA-4208-8235-BCE43275C694}
    07.08.2007  11:53    <DIR>          {D7E04009-B191-4E9D-9D2D-1BBE57BD8A42}

    Open in new window


    Author Comment

    Yes of course, I have GUID, not the "xxxxxxx" : it was just for the example. But how to retreive the real names via the GUID ?
    LVL 86

    Assisted Solution

    Well, these are the real names. The GUIDs are the names of subdirectories in "Installer" - take a look at that directory.

    Author Comment

    But, the programs into these directories are not valids.

    Eg :

    I have a Safari.lnk who give me this path => C:/Windows/Installer/{xxxxxxxx}/SafariIco.exe

    But this path is not the program path ! SafariIco.exe is not a valid Win32 exe.

    Safari is really located at C:/Program Files/Safari/Safari.exe

    Do you understand ?

    Author Comment

    Hm... nobody have the solution ?
    LVL 39

    Accepted Solution

    You could/should pass flag  SLGP_RAWPATH  and/or SLGP_UNCPRIORITY as 4th argument to GetPath.

    You also could/should pass an address of a WIN32_FIND_DATA struct as 3rd argument. The WIN32_FIND_DATA has a cFileName member which should contain the absolute path of the file.

       WIN32_FIND_DATA wfd = { 0 };
       if (NOERROR != psl->GetPath(szTarget, cchTarget, &wfd, SLGP_UNCPRIORITY ) )
            goto cleanup;

      // now check for wfd.cFileName

    Author Comment

    Hello, thanks for your answer

    I have tested with SLGP_RAWPATH  and/or SLGP_UNCPRIORITY => no changes

    I have also tested with WIN32_FIND_DATA wfd = { 0 }; and a printf with wfd.cFileName, it just returns "taller" or "taller\{XXXX-XXXX-XXX" (the GUID is not complete)

    Author Comment

    Nobody have another solution ?

    Featured Post

    Highfive Gives IT Their Time Back

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    Join & Write a Comment

    Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
    Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
    The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
    The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

    746 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    15 Experts available now in Live!

    Get 1:1 Help Now