传统应用的快捷方式目标指向可执行文件的路径,但是对于市肆应用(也叫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解析出安装目录
PackageManager是WinRT的范例,如何在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());
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |