AmirMasoud Fallahi
AmirMasoud Fallahi

Reputation: 75

winapi create shortcut failed

I want to create shortcut of a file. I found this Microsoft page that describe how to write this, and I copy that in my code to use. But I have some problems, first it had the following error: "CoInitialize has not been called." I add this CoInitialize(nullptr); to solve the error, but I have error yet.

when I debug it, it has "Information not available, no symbols loaded for windows.storage.dll" error on this line:

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

and after execution when I see the destination path, it creates a shortcut with the name but i can't open it, and it hasn't any content.

What wrong with this?

Does the error make this problem?

I'm using VS 2012.

Code Edited:

// #include "stdafx.h"
#include "windows.h"
#include "shobjidl.h"
#include <iostream>
#include <shlwapi.h>
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"

HRESULT CreateLink(LPCWSTR, LPCWSTR, LPCWSTR);

void wmain(int argc, wchar_t* argv[ ], wchar_t* envp[ ])
{

    WCHAR lpwSource[MAX_PATH] = {0};
    lstrcpyW(lpwSource, (LPCWSTR)argv[1]);

    WCHAR lpwDest[MAX_PATH] = {0};
    lstrcpyW(lpwDest, (LPCWSTR)argv[2]);

    HRESULT hResult = 0;
    hResult = CreateLink(lpwSource, lpwDest, NULL);

    if (hResult == S_OK) {

        printf("Shortcut was created successfully.\n");

    } else {

        printf("Shortcut creation failed.\n");

    }

    getchar();
}

HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc)
{
    HRESULT hres = 0;
    IShellLink* psl;

    HRESULT hCoInit = 0;
    hCoInit = CoInitialize(nullptr);

    // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
    // has already been called.
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
    if (SUCCEEDED(hres)) {
        IPersistFile* ppf;

        // Set the path to the shortcut target and add the description. 
        psl->SetPath(lpszPathObj);
        psl->SetDescription(lpszDesc);

        // Query IShellLink for the IPersistFile interface, used for saving the 
        // shortcut in persistent storage. 
        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);

        if (SUCCEEDED(hres)) {
            // Save the link by calling IPersistFile::Save. 
            hres = ppf->Save(lpszPathLink, TRUE);
            ppf->Release();
        }
        psl->Release();
    }
    return hres;
}

Upvotes: 2

Views: 214

Answers (1)

CristiFati
CristiFati

Reputation: 41147

As I specified in my comment, I've built the code (previous version (Question VERSION #2.) from the one at answer time - which BTW was containing some string conversions that would have most likely failed on non English locales) with VStudio 2013 and ran it on my Win 10 (English) machine. It created a valid shortcut.

So, there was nothing wrong with the code (in the sense that it wouldn't work).
The problem was that the output file was also having the .png extension, and when opening it, Win would attempt to use the default image viewer / editor, which would treat the file as PNG (based on its extension).
That is obviously wrong, as .lnk files have their own format (as I briefly explained in [SO]: What is the internal structure of a Windows shortcut? (@CristiFati's answer)).

The solution was to properly name the shortcut (let it have the .lnk extension).

Some additional (non critical) notes about the code (current state):

  • No need for C++ (11) features (nullptr (also check next bullet)):

    HRESULT hCoInit = CoInitialize(NULL);
    
  • Reorganize the #includes. Use the following list:

    #include <windows.h>
    #include <shobjidl.h>
    #include <shlguid.h>
    #include <stdio.h>
    

Upvotes: 3

Related Questions