How to list installed StoreApps and their identifier in Windows 8 and 10

What I want to get is the AppUserModelId of all installed StoreApp applications, so I can pass it to IApplicationActivationManager->ActivateApplication .

On Windows 8, it was saved in the registry, but on Windows 10 it no longer works.

There are a lot of questions about this on the Internet, but even after several days of searching, I could not find a satisfactory solution.

So far, I have been as follows:

  • I am creating an instance of IPackageManager ,
  • I call FindPackagesByUserSecurityId() with the SID of the current user,
  • I repeat the returned collection
  • I get the IPackage interface
  • From this, I get the IPackageId interface,
  • Then I call IPackageId->get_FamilyName()

With this, I have, for example, in Windows 10 for Windows Calculator the line " Microsoft.WindowsCalculator_8wekyb3d8bbwe ".

When I add " !App " to this line, I have the full AppUserModelId to start the Windows calculator: " Microsoft.WindowsCalculator_8wekyb3d8bbwe!App "

But not all applications use the " !App " named FamilyName. For example, Spartan uses the AppUserModelId " Microsoft.Windows.Spartan_cw5n1h2txyewy!Microsoft.Spartan.Spartan ", which does not end with " !App ". And when I replace " !Microsoft.Spartan.Spartan " with " !App ", it does not start → "This application does not support the specified contract."

So my question is: where can I get the last missing piece?

I found PowerShell code on the Internet ( http://poshcode.org/5702 ) that seems to do something very similar:

 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 } } } } 

I really don't understand this cryptic PowerShell stuff, but one line seems interesting to me:

 foreach($Application in $_.Package.Applications.Application) 

This seems to be an enumeration of applications in a package.

A comment in the same PowerShell code says:

 # The full AppUserModelId is composed of the package name, the publisher id, and the app id, such as Microsoft.ZuneMusic_8wekyb3d8bbwe!Microsoft.ZuneMusic 

so that $Application.Id missing.

If I could get the IAppInfo interface, I could call IAppInfo->get_Id() , and I would be ready.

But I do not know how to get this from IPackage in C ++.

+2
source share
2 answers

It is incredible that no one has an idea! This shows how Microsoft makes us hard. Such a universal task, as listing installed StoreApps with their AppUserModelId, requires a specialized research department.

I finally came up with a solution that works great on Windows 8 and Windows 10. But it takes a lot of code.

It seems that Windows does not contain the application identifier in memory, and the API does not have a direct definition. I examined all the header files in the Windows 10 SDK and could not find the appropriate interface useful for this task.

But I found out how to get them. I continue after 6 steps in my question:

  1. call IPackage->get_InstalledLocation() , which returns IStorageFolder .
  2. QueryInterface for IStorageItem
  3. call IStorageItem->get_Path()

Now you have a way to install the application. Windows 10 uses two base folders:

  • C: \ Program Files \ WindowsApps
  • C: \ Windows \ SystemApps

and several others, such as

  • C: \ Windows \ vpnplugins
  • C: \ Windows \ devicesflow
  • C: \ Windows \ MicracastView
  • C: \ Windows \ PrintDialog
  • C: \ Windows \ PrintDialog3D
  • C: \ Windows \ WinStore

In the path of the returned folder, you will find the file " AppxManifest.xml ". This file looks like this:

 <?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> 

And voila, here they are. This package has two application identifiers: " microsoft.windowslive.mail " and " microsoft.windowslive.calendar ".

Then you take the FamilyName package from step 6, adding "!" and add this identifier and everything will be ready.

This package can be launched using IApplicationActivationManager->ActivateApplication() using one of the AppUserModelId parameters:

  • " microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.calendar "
  • " microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.mail "
+3
source

Use the PackageManager APIs to list packages and GetPackageApplicationIds to list applications in a package, for example. pseudo code

 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 } 

See GetPackageApplicationIds () on MSDN for more information, including a working sample code https://msdn.microsoft.com/en-us/library/windows/desktop/dn270603(v=vs.85).aspx

0
source

All Articles