Как перечислить установленные StoreApps и их ID в Windows 8 и 10

Я хочу получить AppUserModelId всех установленных приложений StoreApp, чтобы я мог передать его IApplicationActivationManager->ActivateApplication,

В Windows 8 он был сохранен в реестре, но в Windows 10 его больше нет.

В интернете много вопросов по этому поводу, но даже после нескольких дней поиска я не смог найти удовлетворительного решения.

Что я имею до сих пор, так это следующее:

  1. Я создаю экземпляр IPackageManager,
  2. Я звоню FindPackagesByUserSecurityId() с SID текущего пользователя,
  3. Я перебираю возвращенную коллекцию
  4. Я получаю IPackage интерфейс
  5. От этого я получаю IPackageId интерфейс,
  6. Тогда я звоню IPackageId->get_FamilyName()

С этим у меня например на Windows 10 для калькулятора Windows строка «Microsoft.WindowsCalculator_8wekyb3d8bbwe».

Когда я добавляю к этой строке «!App«У меня есть полный AppUserModelId для запуска калькулятора Windows:»Microsoft.WindowsCalculator_8wekyb3d8bbwe!App«

Но не все приложения используют «!App«За фамилией.
Например, Spartan использует AppUserModelId
«Microsoft.Windows.Spartan_cw5n1h2txyewy!Microsoft.Spartan.Spartan«который не заканчивается»!App«. И когда я заменю»!Microsoft.Spartan.Spartan» с «!Appmsgstr «это не запустится ->» Это приложение не поддерживает указанный контракт «.

Итак, мой вопрос: откуда мне взять последнюю недостающую часть?

Я нашел код 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

так что не хватает это $Application.Id,

Если бы я мог получить IAppInfo интерфейс в любом случае я мог бы позвонить IAppInfo->get_Id() и я был бы готов.

Но я не знаю, как получить это от IPackage в C ++.

2

Решение

Невероятно, что ни у кого нет идеи!
Это показывает, как Microsoft усложняет нам жизнь.
Такая универсальная задача, как перечисление установленных StoreApps с их AppUserModelId, требует отдела научных исследований.

Я наконец-то пришел к решению, которое отлично работает на Windows 8 и Windows 10. Но требуется много кода.

Похоже, что Windows не хранит идентификаторы приложений в памяти, и нет API для их непосредственного определения. Я изучил все заголовочные файлы в Windows 10 SDK и не смог найти соответствующий интерфейс, полезный для этой задачи.

Но я узнал, как их получить. Я продолжаю после 6 шагов в моем вопросе:

  1. вызов IPackage->get_InstalledLocation() который возвращает IStorageFolder,
  2. QueryInterface для IStorageItem
  3. вызов IStorageItem->get_Path()

Теперь у вас есть путь, где установлено приложение. Windows 10 использует две базовые папки:

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

и несколько других, как

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

В возвращенном пути к папке вы найдете файл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>

И вуаля, вот они. Этот пакет имеет два идентификатора приложения: «microsoft.windowslive.mail» а также «microsoft.windowslive.calendar».

Затем вы берете пакет FamilyName из шага 6 и добавляете «!» и добавьте этот идентификатор, и все готово.

Этот пакет может быть запущен с IApplicationActivationManager->ActivateApplication() используя один из AppUserModelId:

  • «microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.calendar«
  • «microsoft.windowscommunicationsapps_8wekyb3d8bbwe!microsoft.windowslive.mail«
3

Другие решения

Используйте API PackageManager для перечисления пакетов и 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
}

Посмотрите GetPackageApplicationIds () на MSDN для получения дополнительной информации, включая рабочий пример кода
https://msdn.microsoft.com/en-us/library/windows/desktop/dn270603(v=vs.85).aspx

0