创建托管应用Create hosted apps

从 Windows 10 版本2004开始,你可以创建 托管应用Starting in Windows 10, version 2004, you can create hosted apps. 托管应用与父 主机 应用共享相同的可执行文件和定义,但其外观和行为类似于系统上的单独应用。A hosted app shares the same executable and definition as a parent host app, but it looks and behaves like a separate app on the system.

对于希望组件(如可执行文件或脚本文件)的行为类似于独立 Windows 10 应用,但该组件需要托管进程才能进行执行的应用场景,托管应用会很有用。Hosted apps are useful for scenarios where you want a component (such as an executable file or a script file) to behave like a standalone Windows 10 app, but the component requires a host process in order to execute. 例如,可以将 PowerShell 或 Python 脚本作为托管应用传递,该应用需要安装主机才能运行。For example, a PowerShell or Python script could be delivered as a hosted app that requires a host to be installed in order to run. 托管应用可以具有其自己的开始磁贴、标识,且可以与 Windows 10 功能(如后台任务、通知、磁贴和共享目标)深度集成。A hosted app can have its own start tile, identity, and deep integration with Windows 10 features such as background tasks, notifications, tiles, and share targets.

包清单中的几个元素和属性支持托管应用功能,包清单中的这些元素和特性使托管应用可以在主机应用包中使用可执行文件和定义。The hosted apps feature is supported by several elements and attributes in the package manifest that enable a hosted app to use an executable and definition in a host app package. 当用户运行托管应用程序时,操作系统会自动以托管应用程序的标识启动主机可执行文件。When a user runs the hosted app, the OS automatically launches the host executable under the identity of the hosted app. 然后,宿主可以将视觉资产、内容或调用 Api 作为托管应用程序加载。The host can then load visual assets, content, or call APIs as the hosted app. 托管应用获取主机和托管应用之间声明的功能的交集。The hosted app gets the intersection of capabilities declared between the host and hosted app. 这意味着,托管应用无法请求比主机提供的功能更多的功能。This means that a hosted app cannot ask for more capabilities than what the host provides.

定义主机Define a host

宿主是托管应用程序的主要可执行文件或运行时进程。The host is the main executable or runtime process for the hosted app. 目前,唯一受支持的主机是包含 包标识 ( .Net 或 c + +/Win32) 的桌面应用程序。Currently, the only supported hosts are desktop apps (.NET or C++/Win32) that have package identity. 此时不支持将 UWP 应用作为主机。UWP apps are not supported as hosts at this time. 对于桌面应用程序,有多种方式具有包标识:There are several ways for a desktop app to have package identity:

  • 将程序包标识授予桌面应用最常见的方法是将 其打包到 .msix 包中The most common way to grant package identity to a desktop app is by packaging it in an MSIX package.
  • 在某些情况下,你也可以选择通过创建 稀疏包来授予包标识。In some cases, you may alternatively choose to grant package identity by creating a sparse package. 如果无法采用 .MSIX 打包来部署桌面应用,则此选项很有用。This option is useful if you are unable to adopt MSIX packaging for deploying your desktop app.

宿主是在其包清单中通过 uap10: HostRuntime 扩展声明的。The host is declared in its package manifest by the uap10:HostRuntime extension. 此扩展具有一个 Id 属性,该属性必须为托管应用程序的包清单所引用的值赋值。This extension has an Id attribute that must be assigned a value that is also referenced by the package manifest for the hosted app. 激活托管应用后,主机将以托管应用程序的标识启动,并可以从托管应用程序包加载内容或二进制文件。When the hosted app is activated, the host is launched under the identity of the hosted app and can load content or binaries from the hosted app package.

下面的示例演示如何在包清单中定义主机。The following example demonstrates how to define a host in a package manifest. Uap10: HostRuntime扩展在包范围内,因此将声明为package元素的子元素。The uap10:HostRuntime extension is package-wide and is therefore declared as a child of the Package element.

<Package xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10">

  <Extensions>
    <uap10:Extension Category="windows.hostRuntime"  
        Executable="PyScriptEngine\PyScriptEngine.exe"  
        uap10:RuntimeBehavior="packagedClassicApp"  
        uap10:TrustLevel="mediumIL">
      <uap10:HostRuntime Id="PythonHost" />
    </uap10:Extension>
  </Extensions>

</Package>

请注意以下有关以下元素的重要详细信息。Make note of these important details about the following elements.

元素Element 详细信息Details
uap10:Extensionuap10:Extension windows.hostRuntime类别声明一个包范围扩展,该扩展定义激活托管应用时要使用的运行时信息。The windows.hostRuntime category declares a package-wide extension that defines the runtime information to be used when activating a hosted app. 托管应用将使用扩展中声明的定义运行。A hosted app will run with the definitions declared in the extension. 使用在前面的示例中声明的主机应用时,托管应用将作为可执行 PyScriptEngine.exe 文件在 mediumIL 信任级别运行。When using the host app declared in the previous example, a hosted app will run as the executable PyScriptEngine.exe at the mediumIL trust level.

可执行文件uap10: RuntimeBehavioruap10: TrustLevel属性指定包中主机进程二进制文件的名称,以及托管应用的运行方式。The Executable, uap10:RuntimeBehavior, and uap10:TrustLevel attributes specify the name of the host process binary in the package and how the hosted apps will run. 例如,使用上一示例中的属性的托管应用将作为可执行 PyScriptEngine.exe 文件在 mediumIL 信任级别运行。For example, a hosted app using the attributes in the previous example will run as the executable PyScriptEngine.exe at mediumIL trust level.
uap10:HostRuntimeuap10:HostRuntime Id属性声明包中此特定主机应用的唯一标识符。The Id attribute declares the unique identifier of this specific host app in the package. 一个包可以有多个主机应用程序,每个应用程序必须有一个具有唯一Iduap10: HostRuntime元素。A package can have multiple host apps, and each must have a uap10:HostRuntime element with a unique Id.

声明托管应用Declare a hosted app

托管应用主机上声明了包依赖关系。A hosted app declares a package dependency on a host. 托管应用利用主机 ID (即,主机) 包中的uap10: HostRuntime扩展的id属性用于激活,而不是在其自己的包中指定入口点可执行文件。The hosted app leverages the host's ID (that is, the Id attribute of the uap10:HostRuntime extension in the host package) for activation instead of specifying an entry point executable in its own package. 托管应用通常包含主机可能访问的内容、视觉资产、脚本或二进制文件。The hosted app typically contains content, visual assets, scripts, or binaries that may be accessed by the host. 托管应用程序包中的 y 值的目标值应与主机的值相同。The TargetDeviceFamily value in the hosted app package should target the same value as the host.

托管应用包可以签名或无符号:Hosted app packages can be signed or unsigned:

  • 已签名的包可能包含可执行文件。Signed packages may contain executable files. 这在具有二进制扩展机制的方案中很有用,此机制使宿主能够在托管应用程序包中加载 DLL 或已注册的组件。This is useful in scenarios that have a binary extension mechanism, which enables the host to load a DLL or registered component in the hosted app package.
  • 未签名的包只能包含不可执行的文件。Unsigned packages can only contain non-executable files. 当宿主只需要加载映像、资产和内容或脚本文件时,这非常有用。This is useful in scenarios where the host only needs to load images, assets and content or script files. 未签名 OID 的包在其 Identity 元素中必须包含一个特殊值,否则不允许注册。Unsigned packages must include a special OID value in their Identity element or they won’t be allowed to register. 这可以防止未签名的包与签名包的标识冲突,或哄骗签名包的标识。This prevents unsigned packages from conflicting with or spoofing the identity of a signed package.

若要定义托管应用,请在包清单中声明以下项:To define a hosted app, declare the following items in the package manifest:

下面的示例演示了一个未签名的托管应用程序包清单的相关部分。The following example demonstrates the relevant sections of a package manifest for an unsigned hosted app.

<Package xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10">

  <Identity Name="NumberGuesserManifest"
    Publisher="CN=AppModelSamples, OID.2.25.311729368913984317654407730594956997722=1"
    Version="1.0.0.0" />

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.19041.0" />
    <uap10:HostRuntimeDependency Name="PyScriptEnginePackage" Publisher="CN=AppModelSamples" MinVersion="1.0.0.0"/>
  </Dependencies>

  <Applications>
    <Application Id="NumberGuesserApp"  
      uap10:HostId="PythonHost"  
      uap10:Parameters="-Script &quot;NumberGuesser.py&quot;">
    </Application>
  </Applications>

</Package>

请注意以下有关以下元素的重要详细信息。Make note of these important details about the following elements.

元素Element 详细信息Details
标识Identity 由于本示例中的托管应用包是无符号的,因此 发布服务器 特性必须包含 OID.2.25.311729368913984317654407730594956997722=1 字符串。Because the hosted app package in this example is unsigned, the Publisher attribute must include the OID.2.25.311729368913984317654407730594956997722=1 string. 这可确保未签名的包无法欺骗签名包的标识。This ensures that the unsigned package cannot spoof the identity of a signed package.
TargetDeviceFamilyTargetDeviceFamily MinVersion特性必须指定10.0.19041.0 或更高版本的 OS 版本。The MinVersion attribute must specify 10.0.19041.0 or a later OS version.
uap10:HostRuntimeDependencyuap10:HostRuntimeDependency 此元素元素声明主机应用包上的依赖关系。This element element declares a dependency on the host app package. 这包括主机包的名称和发布服务器****以及它所依赖的文件****名称This consists of the Name and Publisher of the host package, and the MinVersion it depends on. 这些值可在主机包的 标识 元素下找到。These values can be found under the Identity element in the host package.
应用程序Application Uap10: HostId属性表示主机上的依赖关系。The uap10:HostId attribute expresses the dependency on the host. 托管应用包必须为应用程序扩展元素声明此特性,而不是常用的可执行文件入口点特性。The hosted app package must declare this attribute instead of the usual Executable and EntryPoint attributes for an Application or Extension element. 因此,托管应用从具有相应HostId值的主机继承可执行文件入口点和运行时属性。As a result, the hosted app inherits the Executable, EntryPoint and runtime attributes from the host with the corresponding HostId value.

Uap10: Parameters特性指定传递给宿主可执行文件的入口点函数的参数。The uap10:Parameters attribute specifies parameters that are passed to the entry point function of the host executable. 由于主机需要知道要如何处理这些参数,主机和托管应用之间有隐含的协定。Because the host needs to know what to do with these parameters, there is an implied contract between the host and hosted app.

在运行时注册未签名的托管应用程序包Register an unsigned hosted app package at run time

Uap10: HostRuntime扩展的一个优点是,它允许主机在运行时动态生成托管应用包,并使用PackageManager API 注册它,而无需对其进行签名。One benefit of the uap10:HostRuntime extension is that it enables a host to dynamically generate a hosted app package at runtime and register it by using the PackageManager API, without needing to sign it. 这样一来,主机就可以为所承载的应用包动态生成内容和清单,然后注册它。This enables a host to dynamically generate the content and manifest for the hosted app package and then register it.

使用 PackageManager 类的以下方法来注册未签名的托管应用程序包。Use the following methods of the PackageManager class to register an unsigned hosted app package. 从 Windows 10 版本2004开始提供这些方法。These methods are available starting in Windows 10, version 2004.

  • AddPackageByUriAsync:使用Options参数的AllowUnsigned属性注册未签名的 .msix 包。AddPackageByUriAsync: Registers an unsigned MSIX package by using the AllowUnsigned property of the options parameter.
  • RegisterPackageByUriAsync:执行松散的包清单文件注册。RegisterPackageByUriAsync: Performs a loose package manifest file registration. 如果对包进行了签名,则包含清单的文件夹必须包含 时会文件 和目录。If the package is signed, the folder containing the manifest must include a .p7x file and catalog. 如果未签名,则必须设置options参数的AllowUnsigned属性。If unsigned, the AllowUnsigned property of the options parameter must be set.

未签名的托管应用的要求Requirements for unsigned hosted apps

  • 包清单中的 应用程序扩展 元素不能包含激活数据,如 ExecutableEntryPointTrustLevel 属性。The Application or Extension elements in the package manifest cannot contain activation data such as the Executable, EntryPoint, or TrustLevel attributes. 相反,这些元素只能包含表示主机上的依赖项的 uap10: HostId 特性和 uap10: Parameters 特性。Instead, these elements can only contain a uap10:HostId attribute that expresses the dependency on the host and a uap10:Parameters attribute.
  • 包必须是主包。The package must be a main package. 它不能是捆绑包、框架包、资源或可选包。It cannot be a bundle, framework package, resource, or optional package.

安装和注册未签名的托管应用程序包的主机的要求Requirements for a host that installs and registers an unsigned hosted app package

示例Sample

有关将自身声明为主机,然后在运行时动态注册托管应用包的功能完整的示例应用,请参阅 托管应用示例For a fully functional sample app that declares itself as a host and then dynamically registers a hosted app package at runtime, see the hosted app sample.

主机The host

主机名为 PyScriptEngineThe host is named PyScriptEngine. 这是用 c # 编写的包装程序,用于运行 python 脚本。This is a wrapper written in C# that runs python scripts. 当使用参数运行时 -Register ,脚本引擎将安装包含 python 脚本的托管应用程序。When run with the -Register parameter, the script engine installs a hosted app containing a python script. 当用户尝试启动新安装的托管应用时,主机将启动并执行 NumberGuesser python 脚本。When a user tries to launch the newly installed hosted app, the host is launched and executes the NumberGuesser python script.

主机应用的包清单 (PyScriptEnginePackage 文件夹中的 appxmanifest.xml 文件) 包含一个 uap10: HostRuntime 扩展,该扩展将应用声明为 ID 为 PythonHost 的主机和可执行 PyScriptEngine.exeThe package manifest for the host app (the Package.appxmanifest file in the PyScriptEnginePackage folder) contains a uap10:HostRuntime extension that declares the app as a host with the ID PythonHost and the executable PyScriptEngine.exe.

备注

在此示例中,包清单的名称为 appxmanifest.xml,它是 Windows 应用程序打包项目的一部分。In this sample, the package manifest is named Package.appxmanifest and it is part of a Windows Application Packaging Project. 生成此项目时,它会 生成一个名为 AppxManifest.xml的清单 ,并为主机应用程序生成 .msix 包。When this project is built, it generates a manifest named AppxManifest.xml and builds the MSIX package for the host app.

托管应用The hosted app

托管应用由 python 脚本和包项目(如包清单)组成。The hosted app consists of a python script and package artifacts such as the package manifest. 它不包含任何 PE 文件。It doesn’t contain any PE files.

托管应用的包清单 (NumberGuesser/AppxManifest.xml 文件) 包含以下项:The package manifest for the hosted app (the NumberGuesser/AppxManifest.xml file) contains the following items:

  • 标识元素的发行者特性包含 OID.2.25.311729368913984317654407730594956997722=1 无符号包所需的标识符。The Publisher attribute of the Identity element contains the OID.2.25.311729368913984317654407730594956997722=1 identifer, which is required for an unsigned package.
  • 应用程序元素的uap10: HostId属性将PythonHost标识为其主机。The uap10:HostId attribute of the Application element identifies PythonHost as its host.

运行示例Run the sample

该示例需要10.0.19041.0 或更高版本的 Windows 10 和 Windows SDK。The sample requires version 10.0.19041.0 or later of Windows 10 and the Windows SDK.

  1. 示例 下载到开发计算机上的文件夹。Download the sample to a folder on your development computer.

  2. 在 Visual Studio 中打开 PyScriptEngine 解决方案,并将 PyScriptEnginePackage 项目设置为启动项目。Open the PyScriptEngine.sln solution in Visual Studio and set the PyScriptEnginePackage project as the startup project.

  3. 生成 PyScriptEnginePackage 项目。Build the PyScriptEnginePackage project.

  4. 在解决方案资源管理器中,右键单击 PyScriptEnginePackage 项目并选择 " 部署"。In Solution Explorer, right-click the PyScriptEnginePackage project and choose Deploy.

  5. 在将示例文件复制到的目录中打开一个命令提示符窗口,并运行以下命令,将示例 NumberGuesser 应用注册 (托管应用) 。Open a Command Prompt window to the directory where you copied the sample files and run the following command to register the sample NumberGuesser app (the hosted app). 更改 D:\repos\HostedApps 为复制示例文件的路径。Change D:\repos\HostedApps to the path where you copied the sample files.

    D:\repos\HostedApps>pyscriptengine -Register D:\repos\HostedApps\NumberGuesser\AppxManifest.xml
    

    备注

    可以 pyscriptengine 在命令行上运行,因为示例中的主机声明了 AppExecutionAliasYou can run pyscriptengine on the command line because the host in the sample declares an AppExecutionAlias.

  6. 打开 " 开始 " 菜单,单击 " NumberGuesser " 运行托管应用。Open the Start menu and click NumberGuesser to run the hosted app.