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

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

xuwenyan2年前 (2021-02-04)c++1344

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)并添加到开始菜单、桌面、任务栏” 的相关文章

    C++如何实现远程注入dll

    C++如何实现远程注入dll

    如何把我们的代码放到别人的进程里面运行?我们需要做一个dll动态库,然后使用远程注入技术,将我们的dll注入到别人的进程里面,然后加载起来。这样我们的代码就可以在别人的进程里面工作了。注入代码#include "stdafx.h" int EnableD...

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

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

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

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

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

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

    static_assert和assert有什么区别?

    static_assert和assert有什么区别?

    static_assert和assert都是断言,都可用于判断一个条件是否成立,并且在条件不成立时及时给出错误提示。那它们用什么不同和需要注意的地方呢? 1:static_assert在编译期执行,而assert在运行期执行。2:static_assert无论在debug模式还是relea...

    c++为什么不能在构造函数里调用虚函数?

    c++为什么不能在构造函数里调用虚函数?

    c++为什么不能在构造函数里调用虚函数? c++的构造顺序先构造父类,然后构造子类,析构顺序相反。 如果在构造函数调用虚函数,例如:ClassB继承于ClassA,如果在ClassA的构造函数里调用虚函数,此时因为ClassB并没有构造,所以ClassB的成员都没有初始化,如果编译执行...

    堆和栈有什么区别?哪个比较快?

    堆和栈有什么区别?哪个比较快?

    我们都知道,windows内存区域无外乎堆、栈、静态区、常量区,下面主要说一说堆和栈。 首先我们要注意一个容易混淆的点,我们经常会听人把堆栈连起来说,通常堆栈指的是栈,而不是堆。 什么是堆? 需要程序员自己申请,并指明大小。 什么是栈? 由编译器自动分配释放 ,存放为...