我想得到的是所有已安装的StoreApp应用程序的AppUserModelId,以便我可以将它传递给IApplicationActivationManager->ActivateApplication
。
在Windows 8中,它被存储在registry中,但在Windows 10中已不再存在。
在互联网上有很多关于这个问题,但即使经过几天的search,我找不到一个令人满意的解决scheme。
我到目前为止是以下几点:
IPackageManager
的实例, FindPackagesByUserSecurityId()
IPackage
接口 IPackageId
接口, IPackageId->get_FamilyName()
与此我举例来说,在Windows计算机上的Windows 10string“ Microsoft.WindowsCalculator_8wekyb3d8bbwe
”。
当我追加到这个string的“ !App
”我有完整的AppUserModelId启动Windows计算器:“ Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
”
但并不是所有的应用程序都使用FamilyName后面的“ !App
”。 例如,Spartan使用不以“ !App
”结尾的AppUserModelId“ Microsoft.Windows.Spartan_cw5n1h2txyewy!Microsoft.Spartan.Spartan
”。 当我用“ !App
”replace“ !Microsoft.Spartan.Spartan
”时,它将不会启动 – >“这个应用程序不支持指定的合同”。
所以我的问题是我从哪里得到最后一个缺失的部分?
我在网上find了一个PowerShell代码( http://poshcode.org/5702 ),这个代码似乎做了一些非常类似的事情:
Get-AppXPackage $PackageName -pv Package | Get-AppxPackageManifest | % { foreach($Application in $_.Package.Applications.Application) { if($Application.Id -like $AppId) { if($Protocol -and !($Application.Extensions.Extension.Protocol.Name | ? { ($_ + "://") -match (($Protocol -replace '\*','.*') + "(://)?") })) { continue } [PSCustomObject]@{ # Notice the secret magic property: PSTypeName = "Microsoft.Windows.Appx.Application" AppUserModelId = $Package.PackageFamilyName + "!" + $Application.Id } } } }
我真的不明白这个神秘的PowerShell的东西,但有一条线看起来很有趣:
foreach($Application in $_.Package.Applications.Application)
这似乎枚举包中的应用程序。
在同一个PowerShell代码中的评论说:
# The full AppUserModelId is composed of the package name, the publisher id, and the app id, such as Microsoft.ZuneMusic_8wekyb3d8bbwe!Microsoft.ZuneMusic
所以缺less的是$Application.Id
。
如果我能得到一个IAppInfo
接口,无论如何,我可以调用IAppInfo->get_Id()
,我会准备好。
但是我不知道如何从C ++的IPackage
中获得这个。
难以置信,没有人有想法! 这显示了微软如何使我们的生活艰难。 像使用AppUserModelId枚举已安装的StoreApps这样的通用任务需要一个科研部门。
我终于找到了一个能够在Windows 8和Windows 10上完美运行的解决方案。但是需要很多代码。
看起来,Windows并没有在内存中保存应用程序ID,也没有API来直接确定它们。 我研究了Windows 10 SDK中的所有头文件,并找不到对应该任务的相应接口。
但我发现如何得到它们。 我在问题的六个步骤之后继续:
IPackage->get_InstalledLocation()
返回一个IStorageFolder
。 IStorageItem
IStorageItem->get_Path()
现在你已经安装了应用程序的路径。 Windows 10使用两个基本文件夹:
和其他几个人一样
在返回的文件夹路径中,您将找到一个文件“ AppxManifest.xml
”。 这个文件看起来像:
<?xml version="1.0" encoding="utf-8"?> <Package xmlns="....."> ...... ...... <Applications> <Application Id="microsoft.windowslive.mail" Executable="HxMail.exe" EntryPoint="Executable"> ...... ...... </Application> <Application Id="microsoft.windowslive.calendar" Executable="HxCalendarAppImm.exe" EntryPoint="Executable"> ...... ...... </Application> </Applications> </Package>
瞧,他们在那里。 这个软件包有两个应用程序ID:“ microsoft.windowslive.mail
”和“ microsoft.windowslive.calendar
”。
然后你从第6步中取出包的FamilyName后附上一个“!” 并附上这个ID,你就完成了。
这个包可以使用AppUserModelId的IApplicationActivationManager->ActivateApplication()
来IApplicationActivationManager->ActivateApplication()
:
microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.calendar
” microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.mail
” 使用PackageManager API来枚举包和GetPackageApplicationIds枚举包中的应用程序,例如伪代码
FOREACH p IN PackageManager.FindPackagesForUserWithPackageTypes(null, PackageType_Main|PackageType_Optional) { PACKAGE_INFO_REFERENCE pir OpenPackageInfoByFullName(p.Id.FullName, 0, &pir) UINT32 n=0 GetPackageApplicationIds(pir, &n, null, null) BYTE* buffer = new BYTE[n] UINT32 count=0 GetPackageApplicationIds(pir, &n, buffer, &count) ClosePackageInfo(pir) PCWSTR * applicationUserModelIds = reinterpret_cast<PCWSTR*>(buffer); FOR (i=0; i<count; ++i) { PCWSTR applicationUserModelId = applicationUserModelIds[i] } delete [] buffer }
有关更多详细信息,请参阅MSDN上的GetPackageApplicationIds(),其中包括工作示例代码https://msdn.microsoft.com/en-us/library/windows/desktop/dn270603(v=vs.85).aspx