经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++获取商店应用(msix应用)桌面快捷方式的安装目录
来源:cnblogs  作者:HRESULT  时间:2024/6/25 8:51:23  对本文有异议

image

传统应用的快捷方式目标指向可执行文件的路径,但是对于商店应用(也叫msix打包应用),则指向一个奇怪的字符串,使用IShellLink::GetPath获取路径时,则得到的是空字符串,而我们的最终目的是要拿到应用的安装路径,那该怎么办呢?

首先解释一下,那个奇怪的字符串叫AUMID(App User Model Id),由应用包系列名称AppInfo.PackageFamilyName和应用标识符AppInfo.Id组成。

分3步获取安装目录

1,先获取快捷方式的PIDL

  1. HRESULT hr = S_OK;
  2. IShellLinkW* psl = NULL;
  3. IPersistFile* psf = NULL;
  4. LPITEMIDLIST pidlLnk = NULL;
  5. do
  6. {
  7. hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
  8. if (FAILED(hr)) {
  9. break;
  10. }
  11. hr = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&psf);
  12. if (FAILED(hr)) {
  13. break;
  14. }
  15. //加载快捷方式
  16. hr = psf->Load(L"C:\\Users\\Xyy\\Desktop\\Microsoft Teams - 快捷方式.lnk", STGM_READ);
  17. if (FAILED(hr)) {
  18. break;
  19. }
  20. //获取快捷方式
  21. hr = psl->GetIDList(&pidlLnk);
  22. if (FAILED(hr)) {
  23. break;
  24. }
  25. } while (false);
  26. //释放资源
  27. if (pidlLnk) ILFree(pidlLnk);

2,通过PIDL获取应用的AUMID

这里要注意,并非所有拿不到路径的快捷方式都是商店应用,因此要判断快捷方式的父目录是否是FOLDERID_AppsFolder,这是一个虚拟目录

  1. ...
  2. LPITEMIDLIST pidlAppsFolder = NULL;
  3. PWSTR ppszName = NULL;
  4. do
  5. {
  6. ...
  7. //获取FOLDERID_AppsFolder的PIDL
  8. hr = SHGetKnownFolderIDList(FOLDERID_AppsFolder, 0, NULL, &pidlAppsFolder);
  9. if (FAILED(hr)) {
  10. break;
  11. }
  12. //判断当前快捷方式的父目录是否是FOLDERID_AppsFolder
  13. if (!ILIsParent(pidlAppsFolder, pidlLnk, FALSE)) {
  14. printf("此快捷方式不是商店应用");
  15. break;
  16. }
  17. //根据PIDL获取AUMID
  18. hr = SHGetNameFromIDList(pidlLnk, SIGDN_PARENTRELATIVEPARSING, &ppszName);
  19. if (FAILED(hr)) {
  20. break;
  21. }
  22. } while (false);
  23. //释放资源
  24. ...
  25. if (pidlAppsFolder) ILFree(pidlAppsFolder);
  26. if (ppszName) CoTaskMemFree(ppszName);

3,通过AUMID解析出packageFamily,再根据PackageManager解析出安装目录

PackageManagerWinRT的类型,如何在c++中使用WinRT,请参考C++/WinRT

以下代码需要管理员权限才能运行。

  1. //根据AUMID拿到packageFamily
  2. std::wstring fullString(ppszName);
  3. size_t pos = fullString.find(L'!');
  4. if (pos == std::wstring::npos) {
  5. break;
  6. }
  7. std::wstring packageFamily = fullString.substr(0, pos);
  8. std::wstring installPath = L"";
  9. PackageManager packageManager;
  10. //通过packageFamily查找所有包
  11. auto packages = packageManager.FindPackages(packageFamily);
  12. for (auto package : packages) {
  13. auto listEnties = package.GetAppListEntries();
  14. for (auto entry : listEnties) {
  15. if (entry.AppUserModelId() == ppszName) {
  16. installPath == package.InstalledPath();
  17. break;
  18. }
  19. }
  20. if (!installPath.empty()) {
  21. break;
  22. }
  23. }
  24. if (installPath.empty()) {
  25. break;
  26. }
  27. //找到安装目录
  28. printf("找到安装目录:%ls", installPath.c_str());

原文链接:https://www.cnblogs.com/xyycare/p/18265865/cpp-get-msix-lnk-location

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号