1

I want to write a program to create a shortcut for a specific file by using win32 API in c. my IDE is visual studio 2010. I found this page but its sample just not compile and return many errors. I also find this code but this always create a link with Target: "D:\Desktop\㩣睜湩潤獷湜瑯灥摡攮數" and I don't know why. can someone tell me why the sample code of Microsoft is not working or the second one return something in Chinese shape language and also with wrong and constant location for any argument? This is my code for MSDN sample:

#include "stdafx.h"
#include "windows.h"
#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"

void _tmain(int argc, TCHAR  *argv[])
{
    CreateLink(argv[1],__argv[2],argv[3]);
}

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

    // 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)) 
        { 
            WCHAR wsz[MAX_PATH]; 

            // Ensure that the string is Unicode. 
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH); 

            // Add code here to check return value from MultiByteWideChar 
            // for success.

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

and the errors are: 1 error C1083: Cannot open include file: 'stdafx.h' and 2 IntelliSense: cannot open source file "stdafx.h"

4
  • The sample does not contain any main function. Commented Sep 28, 2017 at 20:18
  • 1
    The MSDN sample code works just fine. If it is not working for you then you are not using it correctly. As for the "Chinese" Mojibake you are seeing, it is likely caused by you passing an ANSI string where a Unicode string is expected due to an incorrect typecast. So please, stop showing other people's code and do show YOUR code instead. Commented Sep 28, 2017 at 21:51
  • @RemyLebeau, thanks for your comment, but unfortunately I'm not a c developer but I want to use win32 API to create links for my files. so I tried to edit the existing samples for my purpose. so can you tell me how can pass Unicode string as the argument in command line? I just followed the instruction of that code sample. Commented Sep 28, 2017 at 22:06
  • Calling MultiByteToWideChar unconditionally seems fishy to me. If you're already using wide chars (i.e. if you've defined _UNICODE), then what you have isn't encoded using the ACP. Commented Sep 28, 2017 at 22:18

2 Answers 2

4
CreateLink(argv[1],__argv[2],argv[3]);

This call looks weird. You are using argv[] for two LPCWSTR (const wchar_t *) parameters, but are using __argv[] for an LPCSTR (const char *) parameter. You should change the 2nd parameter to LPCWSTR to match the other parameters, and then use argv[] instead of __argv[].

The TCHAR-based IShellLink works with LP(C)WSTR string parameters, and LP(C)TSTR is LP(C)WSTR when compiling for Unicode. Which you are obviously doing, given that you are passing TCHAR-based argv[] values to LPCWSTR parameters, which will only compile if TCHAR is wchar_t.

IPersistFile::Save() takes only a Unicode string as input, regardless of what TCHAR maps to. You are converting the char* value from __argv[] from ANSI to Unicode, so you may as well just get a Unicode string from argv[] to begin with, and omit the call to MultiByteToWideChar() altogether.

There is no good reason to mix ANSI and Unicode strings like this. This is something the MSDN example is getting wrong.

And since your function parameters are working with Unicode strings, you should use the IShellLinkW interface directly instead of the TCHAR-based IShellLink interface.

Try this:

#include "stdafx.h"
#include "windows.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"

HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc) 
{ 
    HRESULT hres; 
    IShellLinkW* psl; 

    // 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_IShellLinkW, (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; 
}

void _tmain(int argc, TCHAR *argv[])
{
    if (argc > 3)
        CreateLink(argv[1], argv[2], argv[3]);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your help man. but why I still get these errors: C1083: Cannot open include file: 'stdafx.h' and IntelliSense: cannot open source file "stdafx.h". I think these are not relevant to the code.
1

Visual Studio generates stdafx.h and stdafx.cpp when you are using new project wizard. If Create empty project checkmark is marked, it will not generate them. These files are used to build a precompiled header file Projname.pch and a precompiled types file Stdafx.obj

For small projects you can eventually remove #include "stdafx.h", but it would be better to create new project with Create empty project unmarked.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.