当前位置:首页 > c++ > 正文内容

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

xuwenyan3年前 (2021-02-04)c++2288

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固定到任务栏(应用程序或快捷方式)

    文章作者:xuwenyan
    版权声明:本文为本站原创文章,转载请注明出处,非常感谢,如版权漏申明或您觉得任何有异议的地方欢迎与本站取得联系。

    扫描二维码推送至手机访问。

    版权声明:本文由艺文笔记发布,如需转载请注明出处。

    本文链接:https://www.xuwenyan.com/archives/89

    分享给朋友:

    “C++创建快捷方式(lnk、url)并添加到开始菜单、桌面、任务栏” 的相关文章

    Visual Studio编译7z源代码

    Visual Studio编译7z源代码

    源代码下载打开地址https://www.7-zip.org/download.html,选择源码下载,可以选择自己需要的版本下载7z.dll编译1:解压源代码包,打开vs解决方案,CPP7zipBundlesFormat7zFFormat7z.dsw,vs会提示升级,不用管,选择升级。2:修改7z...

    C++指针*为什么靠后会比较好?

    C++指针*为什么靠后会比较好?

    大多数书中和大神的代码里,往往指针的*都是靠变量而不是靠类型的,这主要是为了不造成我们第一眼对变量类型的误解和对指针类型的误解,比如: int* p1,p2 我们一眼看上去是不是通常会觉得p1、p1都是一个int*的指针呢?因为我们通常会误把int*当作一个类型,然而无论int*还是i...

    VC的ATL工程向导同时生成一个PS工程是做什么的?可以不要吗?

    VC的ATL工程向导同时生成一个PS工程是做什么的?可以不要吗?

    例如,我用VC2015的工程向导新建一个ATL的工程名字叫myAtl,那么VC会同时给我生成一个叫做myAtlPS的工程。这个myAtlPS工程是做什么的?什么情况下可以不需要它?什么情况下它又是必须存在的? PS工程是什么?可以不要吗? 这个PS工程叫做代理与存根(proxy&nbs...

    解决程序在xp系统总是莫名奇妙的崩溃问题(/Zc:threadSafeInit- )

    解决程序在xp系统总是莫名奇妙的崩溃问题(/Zc:threadSafeInit- )

    现象:程序在xp系统上面总是莫名其妙的崩溃,检查代码看不出任何问题,感觉代码都很好。即使你远程调试,找到了崩溃的点,当你注释了崩溃点之后,还是会崩溃到别的地方。当你遇到了这种情况的时候,不妨参照一下下面的方法看看,说不定可以解决问题。如何解决?将崩溃程序相关的所有工程代码全部关闭全局变量的线程安全检...

    ATL实现windows右键菜单扩展(ContextMenu)

    ATL实现windows右键菜单扩展(ContextMenu)

    右键菜单,即用户右击shell对象时弹出的上下文菜单(context menu)。本文记录了如何创建右键菜单的基本过程,跟着步骤一步一步来,即可创建出一个右键菜单工程。第一步,新建一个ATL工程Visual Studio—>新建项目—>ATL—>使用默认配置(一直按下一步即可)。注...

    uafxcwd.lib(afxmem.obj) : error LNK2005:

    uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)"解决办法

    如果在编译MFC程序的时候出现下列及类似的错误: 1˃uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 LIBCMTD.lib(new...