2

I need to be able to read the target of a shortcut (a .lnk file).

I have Googled this and found numerous results that I have found to be helpful: http://cboard.cprogramming.com/windows-programming/62962-ishelllink-getpath-dev-cplusplus.html http://www.go4answers.com/Example/get-shortcut-target-cpp-win64-216615.aspx http://msdn.microsoft.com/en-us/library/bb776891%28VS.85%29.aspx http://www.codeproject.com/KB/shell/create_shortcut.aspx

Some of these web pages don't mention which header files I need, and I am unaware how to find this information out.

The code that I am currently trying to get working is this:

#include <windows.h>
#include <string>

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

using namespace std;

int main(void)
{

IShellLink* psl;
wchar_t* tempStr = new wchar_t[MAX_PATH];
string path = "E:\\shortcuts\\myshortcut.lnk";

HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*) &psl);

if (SUCCEEDED(hr))
{
    IPersistFile* ppf;
    hr = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf);
    if (SUCCEEDED(hr))
    {
        hr = ppf->Load(path.c_str(), STGM_READ);

        if (SUCCEEDED(hr))
        {
            WIN32_FIND_DATA wfd;
            psl->GetPath(tempStr, MAX_PATH, &wfd, SLGP_UNCPRIORITY | SLGP_RAWPATH);
        }
    }
}
    return 0;
}

You can probably see that this is mainly from one of the websites above, however they did not mention which headers they used, so I had a good guess (which seems to be working) at which ones to use.

Currently the errors I am getting are:

In function 'int main()':
24|error: no matching function for call to 'IPersistFile::Load(const char*, int)'
29|error: no matching function for call to 'IShellLinkA::GetPath(wchar_t*&, int, WIN32_FIND_DATA*, int)'
||=== Build finished: 2 errors, 0 warnings ===|

I was hoping that someone may be able to give me some advice on this, whether it is just pointing me to some better links or, even better, possibly explaining the above code, how to find out which headers to use and where I am going wrong, or an entirely different solution that achieves the same result.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
OdinX
  • 4,135
  • 1
  • 24
  • 33

1 Answers1

2

All headers are fine, but you are using wide (wchar_t based) and 'normal' (char based) strings incorrectly: IPersistFile::Load takes a wide string while IShellLinkA::GetPath takes a normal string. Using this should compile:

IShellLinkA* psl; //specify the ansi version explicitely
CoInitialize( 0 ); //you forgot this, needed for all COM calls to work
char* tempStr = new char[ MAX_PATH ];
std::wstring path = L"E:\\shortcuts\\myshortcut.lnk";

Also if you just want the path, you can just pass 0 instead of a pointer to a WIN32_FIND_DATA.

stijn
  • 34,664
  • 13
  • 111
  • 163
  • Thanks for the reply. That seems to have sorted some of the errors, however now I am getting an undefined reference to: 'CoInitialize@4','CoCreateInstance@20' and 'IID_IPersistFile'. Could you possibly advise me how to resolve these errors? Thanks – OdinX Jul 13 '11 at 10:23
  • you need to link with ole32.lib – stijn Jul 13 '11 at 10:25
  • I have not done linking before, so could you tell me if this look like the right way to do it? http://stackoverflow.com/questions/5862757/how-do-i-link-to-a-library-with-codeblocks Many thanks – OdinX Jul 13 '11 at 11:15
  • That seems to have done the trick (although I linked ole32.a (is that the same thing?)) I just have one more error: "22|undefined reference to `IID_IPersistFile'" Do you have any advise on how to fix this? Thanks – OdinX Jul 13 '11 at 11:21
  • Ok, no problem now, just needed to link uuid.lib as well and no more errors at the moment :) – OdinX Jul 13 '11 at 11:25
  • Nitpick: It's not a "unicode string", it's a "wide string". The wide string (and moreover, NTFS!) can contain any amount of garbage that's not unicode. – Kerrek SB Jul 13 '11 at 11:59
  • @Kerrek SB true indeed, adjusted the answer – stijn Jul 13 '11 at 12:27