简体   繁体   English

如何枚举Windows 8和10中已安装的StoreApps及其ID

[英]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 . 我要获取的是所有已安装的StoreApp应用程序的AppUserModelId,以便可以将其传递给IApplicationActivationManager->ActivateApplication

In Windows 8 it was stored in the Registry, but in Windows 10 it is not anymore. 在Windows 8中,它存储在注册表中,但是在Windows 10中,它不再存在。

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 , 我创建了IPackageManager的实例,
  2. I call FindPackagesByUserSecurityId() with the SID of the current user, 我用当前用户的SID调用FindPackagesByUserSecurityId()
  3. I iterate through the returned collection 我遍历返回的集合
  4. I get an IPackage interface 我得到一个IPackage界面
  5. From that I get an IPackageId interface, IPackageId ,我得到一个IPackageId接口,
  6. Then I call IPackageId->get_FamilyName() 然后我打电话给IPackageId->get_FamilyName()

With that I have for example on Windows 10 for the Windows Calculator the string " Microsoft.WindowsCalculator_8wekyb3d8bbwe ". 这样,例如,在Windows 10上,Windows计算器的字符串为“ 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 " 当我在此字符串后附加一个“ !App ”时,我具有完整的AppUserModelId来启动Windows计算器:“ Microsoft.WindowsCalculator_8wekyb3d8bbwe!App

But not all applications use an " !App " behind the FamilyName. 但是,并非所有应用程序都在FamilyName后面使用“ !App ”。 For example Spartan uses the AppUserModelId " Microsoft.Windows.Spartan_cw5n1h2txyewy!Microsoft.Spartan.Spartan " which does not end with " !App ". 例如,Spartan使用AppUserModelId“ Microsoft.Windows.Spartan_cw5n1h2txyewy!Microsoft.Spartan.Spartan ”而不以“ !App ”结尾。 And when I replace " !Microsoft.Spartan.Spartan " with " !App " it will not start -> "This app does not support the contract specified". 当我将“ !Microsoft.Spartan.Spartan ”替换为“ !App ”时,它将无法启动->“此应用程序不支持指定的合同”。

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: 我在互联网( http://poshcode.org/5702 )中发现了一个PowerShell代码,该代码似乎执行了非常相似的操作:

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: 我真的不明白PowerShell这个神秘的东西,但是我觉得其中一行很有趣:

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

This seems to enumerate Applications in a Package. 这似乎枚举包中的应用程序。

A comment in the same PowerShell code says: 在同一PowerShell代码中的注释说:

# 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 . 所以缺少的是$Application.Id

If I could get an IAppInfo interface anyhow I could call IAppInfo->get_Id() and I would be ready. 如果我能以任何方式获得IAppInfo接口,我都可以调用IAppInfo->get_Id()并做好准备。

But I don't know how to get this from an IPackage in C++. 但是我不知道如何从C ++的IPackage中获得它。

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. 诸如枚举已安装的StoreApps及其AppUserModelId这样的通用任务需要科研部门。

I finally came to a solution that works perfectly on Windows 8 and Windows 10. But a lot of code is required. 我终于找到了一种可以在Windows 8和Windows 10上完美运行的解决方案。但是需要大量代码。

It seems that Windows does not hold the Application ID's in memory and there is no API to determine them directly. Windows似乎没有在内存中保存应用程序ID,并且没有API可以直接确定它们。 I studied all header files in the Windows 10 SDK and could not find a corresponding interface useful for that task. 我研究了Windows 10 SDK中的所有头文件,但找不到适合该任务的相应接口。

But I found out how to get them. 但是我发现了如何获得它们。 I continue after the 6 steps in my question: 在我的问题中的6个步骤之后,我继续:

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

Now you have the path were the App is installed. 现在,您具有安装该应用程序的路径。 Windows 10 uses two base folders: Windows 10使用两个基本文件夹:

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

and several others like 和其他一些人一样

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

In the returned folder path you will find a file " AppxManifest.xml ". 在返回的文件夹路径中,您将找到一个文件“ 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 ". 该软件包具有两个应用程序ID:“ microsoft.windowslive.mail ”和“ microsoft.windowslive.calendar ”。

Then you take the package's FamilyName from step 6 append an "!" 然后,从第6步中获取程序包的FamilyName,然后附加“!” and append this ID and you are done. 并附加此ID,您就完成了。

This package can be started with IApplicationActivationManager->ActivateApplication() using one of the AppUserModelId's: 可以使用以下一种AppUserModelId从IApplicationActivationManager->ActivateApplication()启动此程序包:

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

Use PackageManager APIs to enumerate packages and GetPackageApplicationIds to enumerate applications in a package eg pseudo-code 使用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
}

See GetPackageApplicationIds() on MSDN for more details including working sample code https://msdn.microsoft.com/en-us/library/windows/desktop/dn270603(v=vs.85).aspx 有关更多详细信息,请参见MSDN上的GetPackageApplicationIds(),包括有效的示例代码https://msdn.microsoft.com/zh-cn/library/windows/desktop/dn270603(v=vs.85).aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM