Elmue Elmue - 5 days ago 9
C++ Question

How to enumerate the installed StoreApps and their ID in Windows 8 and 10

What I want to get is the AppUserModelId of all installed StoreApp applications, so that I can pass it to

IApplicationActivationManager->ActivateApplication
.

In Windows 8 it was stored in the Registry, but in Windows 10 it is not anymore.

There are a lot of questions about this in internet but even after days of searching I could not find a satisfying solution.

What I have so far is the following:


  1. I create an instance of
    IPackageManager
    ,

  2. I call
    FindPackagesByUserSecurityId()
    with the SID of the current user,

  3. I iterate through the returned collection

  4. I get an
    IPackage
    interface

  5. From that I get an
    IPackageId
    interface,

  6. Then I call
    IPackageId->get_FamilyName()



With that I have for example on Windows 10 for the Windows Calculator the string "
Microsoft.WindowsCalculator_8wekyb3d8bbwe
".

When I append to this string an "
!App
" I have the complete AppUserModelId to start the Windows Calculator: "
Microsoft.WindowsCalculator_8wekyb3d8bbwe!App
"

But not all applications use an "
!App
" behind the 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 will not start -> "This app does not support the contract specified".

So my question is where do I get the last missing part from?

I found a PowerShell code in 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 enumerate 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 what is missing is the
$Application.Id
.

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

But I don't know how to get this from an
IPackage
in C++.

Answer

Incredible that nobody has an idea! This shows how Microsoft makes us life hard. Such a universal task like enumerating the installed StoreApps with their AppUserModelId requires a cientific research department.

I finally came to a solution that works perfectly on Windows 8 and Windows 10. But a lot of code is required.

It seems that Windows does not hold the Application ID's in memory and there is no API to determine them directly. I studied all header files in the Windows 10 SDK and could not find a corresponding interface useful for that task.

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

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

Now you have the path were the App is installed. Windows 10 uses two base folders:

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

and several others like

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

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

<?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 voilĂ , there they are. This package has two application ID's: "microsoft.windowslive.mail" and "microsoft.windowslive.calendar".

Then you take the package's FamilyName from step 6 append an "!" and append this ID and you are done.

This package can be started with IApplicationActivationManager->ActivateApplication() using one of the AppUserModelId's:

  • "microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.calendar"
  • "microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.mail"
Comments