How to Programmatically Create a Shortcut Using Win32

How to programmatically create a shortcut using Win32

Try Windows Shell Links. This page also contains a C++ example. Descriptive Snippet:

Using Shell Links

This section contains examples that
demonstrate how to create and resolve
shortcuts from within a Win32-based
application. This section assumes you
are familiar with Win32, C++, and OLE
COM programming.

EDIT: Adding the code sample in case the link dies (and MSDN links do die often.)

// CreateLink - Uses the Shell's IShellLink and IPersistFile interfaces 
// to create and store a shortcut to the specified object.
//
// Returns the result of calling the member functions of the interfaces.
//
// Parameters:
// lpszPathObj - Address of a buffer that contains the path of the object,
// including the file name.
// lpszPathLink - Address of a buffer that contains the path where the
// Shell link is to be stored, including the file name.
// lpszDesc - Address of a buffer that contains a description of the
// Shell link, stored in the Comment field of the link
// properties.

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

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);

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

How to create shortcut with Win32 API and c language

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]);
}

Create Internet shortcut using C++

MSDN provides example code for creating shortcuts with IShellLink. This is also referenced in answers on Stack Overflow, most notably this one: How to programmatically create a shortcut using Win32

For your requirement specifically, note that the IShellLink object provides a method SetArguments. You can use this to specify the URL that will be passed on the command line when running MS Edge.

So let's expand the example CreateLink function, rearrange it a little and add a parameter that lets you provide arguments:

#include <windows.h>
#include <shlobj.h>

HRESULT CreateLink(LPCWSTR lpszShortcut,
LPCWSTR lpszPath,
LPCWSTR lpszArgs,
LPCWSTR lpszDesc)
{
HRESULT hres;
IShellLinkW* psl;

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

psl->SetPath(lpszPath);
psl->SetArguments(lpszArgs);
psl->SetDescription(lpszDesc);

// Save link
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
hres = ppf->Save(lpszShortcut, TRUE);
ppf->Release();
}

psl->Release();
}

return hres;
}

Now all you need is to invoke it correctly. Taking your example as a starting point:

#include <string>

int main()
{
HRESULT hres = CoInitialize(NULL);
if (SUCCEEDED(hres))
{
PWSTR deskPath, programsPath;
SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, &deskPath);
SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, 0, NULL, &programsPath);

std::wstring linkFile = std::wstring(deskPath) + L"\\ShortcutTest.lnk";
std::wstring linkPath = std::wstring(programsPath) + L"\\Microsoft\\Edge\\Application\\msedge.exe";
LPCWSTR linkArgs = L"https://www.stackoverflow.com";
LPCWSTR linkDesc = L"Launch Stack Overflow";

CreateLink(linkFile.c_str(), linkPath.c_str(), linkArgs, linkDesc);

CoTaskMemFree(deskPath);
CoTaskMemFree(programsPath);
}

CoUninitialize();
return 0;
}

Note that I also used the correct extension for the shortcut file, which is .lnk. This is required for Windows to recognize the file as a shortcut.

I also changed the method of acquiring standard folders, as per recommendation in MSDN documentation. You should generally avoid anything that uses MAX_PATH. For clarity I am not testing whether these calls succeed, but you should do so in a complete program.

Create shortcut in windows programmatically

Well, I had to use Shortcut.exe to create shortcut but actually what I needed was a HardLink to a folder but Shortcut.exe would create a SoftLink.

Eventually I used junction.exe to create the HardLink.

Check this post for more information https://stackoverflow.com/questions/46885/how-to-create-symbolic-links-in-windows

C++: How do I create a Shortcut in the Start Menu on Windows

Here is the solution. It uses Qt but it's also possible without. Then just use std::wstring instead of QString. For concatenating the paths and filenames you will then have to use string operations instead of using QDir.

#include <shlobj.h> 

bool createStartMenuEntry(QString targetPath) {
targetPath = QDir::toNativeSeparators(targetPath);

WCHAR startMenuPath[MAX_PATH];
HRESULT result = SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, startMenuPath);

if (SUCCEEDED(result)) {
QString linkPath = QDir(QString::fromWCharArray(startMenuPath)).absoluteFilePath("Shortcut Name.lnk");

CoInitialize(NULL);
IShellLinkW* shellLink = NULL;
result = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&shellLink);
if (SUCCEEDED(result)) {
shellLink->SetPath(targetPath.toStdWString().c_str());
shellLink->SetDescription(L"Shortcut Description");
shellLink->SetIconLocation(targetPath.toStdWString().c_str(), 0);
IPersistFile* persistFile;
result = shellLink->QueryInterface(IID_IPersistFile, (void**)&persistFile);

if (SUCCEEDED(result)) {
result = persistFile->Save(linkPath.toStdWString().c_str(), TRUE);

persistFile->Release();
} else {
return false;
}
shellLink->Release();
} else {
return false;
}
} else {
return false;
}
return true;
}

Thats the part that obtains the location of the start-menu folder:

WCHAR startMenuPath[MAX_PATH];
HRESULT result = SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, startMenuPath);

The rest is then creation of the shortcut. Exchange shortcut name and description for your desired values.

Create sections and shortcuts in them for an application in start menu

When you right-click on an application in the Taskbar or click the ">" button in the Start menu, Windows displays a Jump List.

As described in the linked article, if your application is registered to handle certain file types then the Shell will automatically build the list of recently used files as users open them from Explorer. You don't need to do anything.

If you need to further customize the list, the article explains how.

Creating Shortcut using .Net

I am generting .lnk file programmatically now using Win32 method i.e. (IWshShortcut)shell.CreateShortcut() to create the Shortcut file. And it works like charm. Thanks.!!



Related Topics



Leave a reply



Submit