C++获取商店应用(msix应用)桌面快捷方式的安装目录

msix · 浏览次数 : 0

小编点评

在Windows系统中,传统应用和商店应用(MSIX打包应用)的快捷方式目标指向不同类型的字符串。对于商店应用,其目标字符串为AUMID(App User Model Id),由应用包系列名称AppInfo.PackageFamilyName和应用标识符AppInfo.Id组成。要获取商店应用的安装路径,可以按照以下三个步骤操作: 1. 获取快捷方式的PIDL:通过CoCreateInstance创建IShellLinkW接口,然后调用其QueryInterface获取IPersistFile接口,最后调用psf接口的Load方法加载快捷方式文件,从而获得PIDL。 2. 通过PIDL获取应用的AUMID:通过SHGetKnownFolderIDList获取FOLDERID_AppsFolder的PIDL,然后判断当前快捷方式的父目录是否是FOLDERID_AppsFolder。如果是,则根据PIDL获取AUMID。 3. 通过AUMID解析出packageFamily,并根据PackageManager解析出安装目录:使用PackageManager找到与AUMID对应的包,然后获取包的AppListEntries集合,从中查找与快捷方式中的AUMID匹配的条目,从而获取安装目录。 请注意,在使用上述代码时需要管理员权限,并且可能需要在程序退出前释放所有创建的资源,如ILFree和CoTaskMemFree。此外,如果找不到安装目录,可能需要检查其他位置或返回错误信息。 这段代码展示了如何在Windows系统中获取商店应用的安装路径,但具体实现可能因操作系统版本和Windows API的差异而有所不同。在实际开发中,建议查阅相关文档和示例代码以获取更详细的信息。

正文

image

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

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

分3步获取安装目录

1,先获取快捷方式的PIDL

HRESULT hr = S_OK;
IShellLinkW* psl = NULL;
IPersistFile* psf = NULL;
LPITEMIDLIST pidlLnk = NULL;
do
{
    hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
    if (FAILED(hr)) {
        break;
    }
    hr = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&psf);
    if (FAILED(hr)) {
        break;
    }
    //加载快捷方式
    hr = psf->Load(L"C:\\Users\\Xyy\\Desktop\\Microsoft Teams - 快捷方式.lnk", STGM_READ);
    if (FAILED(hr)) {
        break;
    }
    //获取快捷方式
    hr = psl->GetIDList(&pidlLnk);
    if (FAILED(hr)) {
        break;
    }
} while (false);
//释放资源
if (pidlLnk) ILFree(pidlLnk);

2,通过PIDL获取应用的AUMID

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

...
LPITEMIDLIST pidlAppsFolder = NULL;
PWSTR ppszName = NULL;
do
{
    ...
    //获取FOLDERID_AppsFolder的PIDL
    hr = SHGetKnownFolderIDList(FOLDERID_AppsFolder, 0, NULL, &pidlAppsFolder);
    if (FAILED(hr)) {
        break;
    }
    //判断当前快捷方式的父目录是否是FOLDERID_AppsFolder
    if (!ILIsParent(pidlAppsFolder, pidlLnk, FALSE)) {
        printf("此快捷方式不是商店应用");
        break;
    }
    //根据PIDL获取AUMID
    hr = SHGetNameFromIDList(pidlLnk, SIGDN_PARENTRELATIVEPARSING, &ppszName);
    if (FAILED(hr)) {
        break;
    }
} while (false);
//释放资源
...
if (pidlAppsFolder) ILFree(pidlAppsFolder);
if (ppszName) CoTaskMemFree(ppszName);

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

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

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

//根据AUMID拿到packageFamily
std::wstring fullString(ppszName);
size_t pos = fullString.find(L'!');
if (pos == std::wstring::npos) {
    break;
}
std::wstring packageFamily = fullString.substr(0, pos);

std::wstring installPath = L"";
PackageManager packageManager;
//通过packageFamily查找所有包
auto packages = packageManager.FindPackages(packageFamily);
for (auto package : packages) {
    auto listEnties = package.GetAppListEntries();
    for (auto entry : listEnties) {
        if (entry.AppUserModelId() == ppszName) {
            installPath == package.InstalledPath();
            break;
        }
    }
    if (!installPath.empty()) {
        break;
    }
}
if (installPath.empty()) {
    break;
}
//找到安装目录
printf("找到安装目录:%ls", installPath.c_str());

与C++获取商店应用(msix应用)桌面快捷方式的安装目录相似的内容:

C++获取商店应用(msix应用)桌面快捷方式的安装目录

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

如何获取 C#程序 内核态线程栈

## 一:背景 ### 1. 讲故事 在这么多的案例分析中,往往会发现一些案例是卡死在线程的内核态栈上,但拿过来的dump都是用户态模式下,所以无法看到内核态栈,这就比较麻烦,需要让朋友通过其他方式生成一个蓝屏的dump,这里我们简单汇总下。 ## 二:如何生成内核态dump ### 1. 案例代码

.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法

前言 前段时间有朋友问道一个这样的问题,.NET Core中如何通过Attribute的元数据信息来调用标记的对应方法。我第一时间想到的就是通过C#反射获取带有Custom Attribute标记的类,然后通过依赖注入(DI)的方式获取对应服务的方法并通过反射动态执行类的方法,从而实现更灵活的编程方

c# aveva marine 批量导出图纸到dxf格式

获取图纸数据库 查看代码 public static Dictionary

使用C#/.NET解析Wiki百科数据实现获取历史上的今天

创建一个webapi项目做测试使用。 创建新控制器,搭建一个基础框架,包括获取当天日期、wiki的请求地址等 创建一个Http请求帮助类以及方法,用于获取指定URL的信息 使用http请求访问指定url,先运行一下,看看返回的内容。内容如图右边所示,实际上是一个Json数据。我们主要解析 大事记 部

C语言指针易混淆知识点总结

指针 定义 指针是一个变量,存储另一个变量的内存地址,它允许直接访问和操作内存中的数据,使得程序能够以更灵活和高效的方式处理数据和内存。 获取变量地址:使用取地址符 &。 访问地址上的数据:使用解引用符 *。 例子1 指针是存储另一个变量地址的变量。通过使用取地址符 & 和解引用符 *,我们可以灵活

C#使用SendMessage进行进程间通讯

最近公司有个需求是,拖动文件到桌面图标上,自动打开文件。那么只需在OnStartup事件中通过StartupEventArgs获取文件名然后进行操作即可。操作之后发现当软件已经启动了(单例运行),那么将无法将参数传给业务层。原因是因为跨进程了,那么我们可以通过窗口句柄的方式来进行通讯。 1 publ

C#特性

目录C#特性1. 概括2. 语法定义特性类应用特性获取特性3. 应用场景数据验证序列化和反序列化描述性元数据依赖注入单元测试权限控制AOP(面向切面编程)总结引用 C#特性 1. 概括 C#中的特性是一种用于向代码元素添加元数据的机制。它们允许程序员在代码中添加额外的信息,以影响程序的行为、编译过程

C#反射

目录C#反射概述语法应用场景总结引用 C#反射 概述 C# 反射(Reflection)是一种强大的机制,它允许程序在运行时访问和操作 .NET 程序集中的类型和成员。 获取程序集、模块 和类型成员信息,三者关系介绍请查看。 语法 反射的核心概念是 Type 对象。Type 对象表示一个 .NET

C#/.NET/.NET Core优秀项目和框架精选(坑已挖,欢迎大家踊跃提交PR或者Issues中留言)

前言 注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。 帮助开发者发现功能强大、性能优越、创新前沿、简单易用的C#/.NET/.NET Core优秀项目和框架,无论你是寻找灵感、学习新技术、改进代码质量,还是想拓展自