C++创建快捷方式(lnk、url)并添加到开始菜单、桌面、任务栏

windows快捷方式有lnk和url两种,其中lnk以打开应用程序为主,而url以打开网页链接为主。下面创建快捷方式的方法均是调用Com接口,所以一定要在调用此方法前初始化com接口(CoInitialize)。

创建lnk快捷方式

#include <ShlObj.h>

/**
 * 参数
 *   file:需要打开的文件或应用程序
 *   path:快捷方式保存的路径
 *   desc:快捷方式的描述
 *   work_dir:快捷方式所打开程序的工作路径
 * 返回值:成功返回true,否则返回false
 */
bool CreateLnkShortcut(
  const wchar_t* file,
  const wchar_t* path,
  const wchar_t* desc = nullptr,
  const wchar_t* work_dir = nullptr) {
  IShellLink* pIShellLink = nullptr;
  HRESULT hRes = ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
    IID_IShellLink, (void**)&pIShellLink);
  if (!SUCCEEDED(hRes))
    return false;

  hRes = pIShellLink->SetPath(file);
  if (!SUCCEEDED(hRes))
    return false;

  hRes = pIShellLink->SetDescription(desc);
  if (!SUCCEEDED(hRes))
    return false;

  hRes = pIShellLink->SetWorkingDirectory(work_dir);
  if (!SUCCEEDED(hRes))
    return false;

  IPersistFile* pIPersistFile = nullptr;
  hRes = pIShellLink->QueryInterface(IID_IPersistFile, (void**)&pIPersistFile);
  if (!SUCCEEDED(hRes))
    return false;

  hRes = pIPersistFile->Save(path, TRUE);
  if (!SUCCEEDED(hRes))
    return false;

  pIPersistFile->Release();
  pIShellLink->Release();

  return true;
}

创建url快捷方式

#include <IntShCut.h>
#include <propvarutil.h>

/**
* 参数
*   url:网页地址
*   path:快捷方式保存的路径
*   icon_file:快捷方式的图标文件
*   icon_index:快捷方式的图标索引,默认为第一个图标(0)
* 返回值:成功返回true,否则返回false
*/
bool CreateUrlShortcut(
  const wchar_t* url,
  const wchar_t* path,
  const wchar_t* icon_file = L"",
  const int icon_index = 0) {
  IUniformResourceLocatorW* pIInternetLink = nullptr;
  HRESULT hRes = ::CoCreateInstance(CLSID_InternetShortcut, nullptr, CLSCTX_INPROC_SERVER,
    IID_IUniformResourceLocatorW, (void**)&pIInternetLink);
  if (!SUCCEEDED(hRes))
    return false;

  hRes = pIInternetLink->SetURL(url, IURL_SETURL_FL_GUESS_PROTOCOL);
  if (!SUCCEEDED(hRes))
    return false;

  IPropertySetStorage* pss = nullptr;
  hRes = pIInternetLink->QueryInterface(IID_IPropertySetStorage, (void**)&pss);
  if (SUCCEEDED(hRes)) {
    IPropertyStorage *ps = nullptr;
    hRes = pss->Open(FMTID_Intshcut, STGM_WRITE, &ps);
    if (SUCCEEDED(hRes)) {
      // 设置两个属性,一个图标文件路径,一个图标索引
      PROPSPEC pids[2] = { { PRSPEC_PROPID, PID_IS_ICONFILE },{ PRSPEC_PROPID, PID_IS_ICONINDEX } };
      PROPVARIANT pvar[2] = { 0 };

      // 图标文件
      ::InitPropVariantFromString(icon_file, &pvar[0]);

      // 图标索引,默认0
      ::InitPropVariantFromInt16(icon_index, &pvar[1]);

      ULONG n = sizeof(pids) / sizeof(pids[0]);
      ps->WriteMultiple(n, pids, pvar, 0);
      ps->Commit(STGC_DEFAULT);
      ps->Release();

      ::PropVariantClear(&pvar[0]);
      ::PropVariantClear(&pvar[1]);
    }
    pss->Release();
  }

  IPersistFile *pf = nullptr;
  hRes = pIInternetLink->QueryInterface(IID_IPersistFile, (void**)&pf);
  if (SUCCEEDED(hRes)) {
    pf->Save(path, TRUE);
    pf->Release();
  }

  pIInternetLink->Release();

  return true;
}

将快捷方式添加到桌面(桌面快捷方式)

要创建桌面快捷方式,其实就是创建一个快捷方式并且将之放到桌面即可。调用SHGetSpecialFolderPath接口传入CSIDL_DESKTOPDIRECTORY即可获取到当前用户的桌面路径,有时候需要放到所有用户的桌面 CSIDL_COMMON_DESKTOPDIRECTORY ,但是一般需要管理员权限。

void main() {
  ::CoInitialize(NULL);

  wchar_t desk_path[MAX_PATH] = { 0 };
  ::SHGetSpecialFolderPath(NULL, (LPWSTR)desk_path, CSIDL_DESKTOPDIRECTORY, FALSE);

  wchar_t lnk_path[MAX_PATH] = { 0 };
  ::PathAppend(lnk_path, desk_path);
  ::PathAppend(lnk_path, L"记事本.lnk");
  CreateLnkShortcut(L"C:\\Windows\\system32\\notepad.exe", lnk_path);

  wchar_t url_path[MAX_PATH] = { 0 };
  ::PathAppend(url_path, desk_path);
  ::PathAppend(url_path, L"百度.url");
  CreateUrlShortcut(L"https://www.baidu.com", url_path);

  ::CoUninitialize();
}

将快捷方式添加到开始菜单

和添加到桌面并无不同,唯一需要修改的地方就是把桌面路径改为开始菜单路径即可,也就是SHGetSpecialFolderPath中将CSIDL_DESKTOPDIRECTORY改为CSIDL_PROGRAMS,CSIDL_COMMON_PROGRAMS使用所有用户的开始菜单目录,这个目录一般也需要管理员权限才能写入。

void main() {
  ::CoInitialize(NULL);

  wchar_t programs_path[MAX_PATH] = { 0 };
  ::SHGetSpecialFolderPath(NULL, (LPWSTR)programs_path, CSIDL_PROGRAMS, FALSE);

  wchar_t lnk_path[MAX_PATH] = { 0 };
  ::PathAppend(lnk_path, programs_path);
  ::PathAppend(lnk_path, L"记事本.lnk");
  CreateLnkShortcut(L"C:\\Windows\\system32\\notepad.exe", lnk_path);

  wchar_t url_path[MAX_PATH] = { 0 };
  ::PathAppend(url_path, programs_path);
  ::PathAppend(url_path, L"百度.url");
  CreateUrlShortcut(L"https://www.baidu.com", url_path);

  ::CoUninitialize();
}

将快捷方式添加到任务栏:

调用ShellExecute(NULL, L”taskbarpin”, linkPath, NULL, NULL, 0); // linkPath则是快捷方式文件的路径,但是这个方法在win10已经被禁止了。关于固定到任务栏可以参考本站文章c++ windows固定到任务栏(应用程序或快捷方式)