使用封裝配置的套件建立Package creation with the packaging layout

資產套件引入後,開發人員現在可以有工具,除了建置更多套件類型,還能建置更多套件。With the introduction of asset packages, developers now have the tools to build more packages in addition to more package types. 當應用程式變得更大、更複雜,通常會包含更多套件,管理這些套件的難度會增加(尤其是您在 Visual Studio 以外建置並使用對應檔案)。As an app gets larger and more complex, it will often be comprised of more packages, and the difficulty of managing these packages will increase (especially if you are building outside of Visual Studio and using mapping files). 若要簡化應用程式的封裝結構管理,您可以使用 MakeAppx.exe 支援的封裝配置。To simplify the management of an app’s packaging structure, you can use the packaging layout supported by MakeAppx.exe.

封裝配置是一份描述應用程式封裝結構的 XML 文件。The packaging layout is a single XML document that describes packaging structure of the app. 它會指定應用程式套件組合(主要和選用)、套件組合中的套件,和套件中的檔案。It specifies the bundles of an app (primary and optional), the packages in the bundles, and the files in the packages. 從不同的資料夾、磁碟機和網路位置,可以選取檔案。Files can be selected from different folders, drives, and network locations. 選取或排除檔案,可以使用萬用字元。Wildcards can be used to select or exclude files.

應用程式封裝配置設定之後,在單一命令列呼叫中搭配 MakeAppx.exe 建立應用程式的所有套件。After the packaging layout for an app has been set up, it's used with MakeAppx.exe to create all of the packages for an app in a single command line call. 封裝配置可以編輯修改套件結構,以符合您的部署需要。The packaging layout can be edited to alter the package structure to fit your deployment needs.

簡單封裝配置範例Simple packaging layout example

簡單封裝配置範例看起來如下:Here's an example of what a simple packaging layout looks like:

<PackagingLayout xmlns="http://schemas.microsoft.com/appx/makeappx/2017">
  <PackageFamily ID="MyGame" FlatBundle="true" ManifestPath="C:\mygame\appxmanifest.xml" ResourceManager="false">
    
    <!-- x64 code package-->
    <Package ID="x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="*" SourcePath="C:\mygame\*"/>
        <File ExcludePath="*C:\mygame\*.txt"/>
      </Files>
    </Package>
    
    <!-- Media asset package -->
    <AssetPackage ID="Media" AllowExecution="false">
      <Files>
        <File DestinationPath="Media\**" SourcePath="C:\mygame\media\**"/>
      </Files>
    </AssetPackage>

  </PackageFamily>
</PackagingLayout>

讓我們分解此範例,了解它的運作方式。Let's break this example down to understand how it works.

PackageFamilyPackageFamily

此封裝配置會建立一個具有 x64 架構封裝和「媒體」資產套件的單一一般應用程式套件組合檔案。This packaging layout will create a single flat app bundle file with an x64 architecture package and a “Media” asset package.

PackageFamily 元素用來定義應用程式套件組合。The PackageFamily element is used to define an app bundle. 您必須使用ManifestPath屬性提供套件組合的AppxManifestAppxManifest應與對應於的套件組合架構套件的AppxManifestYou must use the ManifestPath attribute to provide an AppxManifest for the bundle, the AppxManifest should correspond to the AppxManifest for the architecture package of the bundle. ID屬性必須同時提供。The ID attribute must also be provided. 套件建立期間這可搭配 MakeAppx.exe,您可以只建立此套件(如果您想要)而且這將會是所產生套件的檔案名稱。This is used with MakeAppx.exe during package creation so that you can create just this package if you want to, and this will be the file name of the resulting package. FlatBundle屬性用來描述您想要建立何種類型的套件組合,true表示一般套件組合 (請閱讀本文了解詳細資訊),false表示傳統套件組合。The FlatBundle attribute is used to describe what type of bundle you want to create, true for a flat bundle (which you can read more about here), and false for a classic bundle. ResourceManager屬性用來指定此套件組合中的資源套件是否使用 MRT 才能存取檔案。The ResourceManager attribute is used to specify if the resource packages within this bundle will use MRT in order to access the files. 預設是true,但是在 Windows 10(版本 1803),這尚未準備好,所以此屬性必須設為falseThis is by default true, but as of Windows 10, version 1803, this is not yet ready, so this attribute must be set to false.

Package 和 AssetPackagePackage and AssetPackage

PackageFamily中,會定義應用程式套件組合包含或參考的套件。Within the PackageFamily, the packages that the app bundle contains or references are defined. 這裡,架構套件(也稱為主要封裝)使用Package元素定義的,而資產套件使用AssetPackage元素定義的。Here, the architecture package (also called the main package) is defined with the Package element, and the asset package is defined with the AssetPackage element. 架構套件必須指定套件適用的架構,「x64」、「x86」、「arm」或「neutral」其中一項。The architecture package must specify which architecture the package is for, either “x64”, “x86”, “arm”, or “neutral”. (選擇性)也可以再次使用ManifestPath屬性,專為此套件提供AppxManifestYou can also (optionally) directly provide an AppxManifest specifically for this package by using the ManifestPath attribute again. 如果不提供AppxManifest,系統會自動建立一個,從提供給PackageFamilyAppxManifestIf an AppxManifest is not provided, one will be automatically generated from the AppxManifest provided for the PackageFamily.

根據預設,為套件組合中的每個套件產生AppxManifestBy default and AppxManifest will be generated for every package within the bundle. 對於資產套件,您也可以設定AllowExecution屬性。For the asset package, you can also set the AllowExecution attribute. 將此設定為false(預設值),可協助降低應用程式發佈時間,因為不需要執行的套件不會被病毒掃描封鎖發佈程序 (您可以在資產套件簡介深入了解這點)。Setting this to false (the default), will help decrease the publishing time for your app since packages that don’t need to execute won’t have their virus scan block the publishing process (you can learn more about this at Introduction to asset packages).

FilesFiles

在每個套件定義內,您可以使用File元素選取要包含在此套件中的檔案。Within each package definition, you can use the File element to select files to be included in this package. SourcePath屬性是檔案的本機位置。The SourcePath attribute is where the files are locally. 您可以從不同資料夾(藉由提供相對路徑)、不同磁碟機(藉由提供絕對路徑)或甚至網路共用 (藉由像是提供\\myshare\myapp\*)選取檔案。You can select files from different folders (by providing relative paths), different drives (by providing absolute paths), or even network shares (by providing something like \\myshare\myapp\*). DestinationPath是套件中檔案的目的地位置,相對於套件根目錄。The DestinationPath is where the files will end up within the package, relative to the package root. ExcludePath(而不是其他兩個屬性)可以用來選擇要排除的檔案,從相同套件中其他File元素的SourcePath屬性所選取的檔案中。ExcludePath can be used (instead of the other two attributes) to select files to be excluded from the ones selected by other File elements’ SourcePath attributes within the same package.

使用萬用字元,每個File元素可用於來選取多個檔案。Each File element can be used to select multiple files by using wildcards. 一般而言,單一萬用字元 (*) 可用於路徑內任何地方任何次數。In general, single wildcard (*) can be used anywhere within the path any number of times. 不過,單一萬用字元只符合資料夾中的檔案,不符合任何子資料夾。However, a single wildcard will only match the files within a folder and not any subfolders. 例如C:\MyGame\*\*適用於SourcePath以選取檔案C:\MyGame\Audios\UI.mp3C:\MyGame\Videos\intro.mp4,但它無法選取C:\MyGame\Audios\Level1\warp.mp3For example, C:\MyGame\*\* can be used in the SourcePath to select the files C:\MyGame\Audios\UI.mp3 and C:\MyGame\Videos\intro.mp4, but it cannot select C:\MyGame\Audios\Level1\warp.mp3. 雙重萬用字元 (**) 也可以用來取代資料夾或檔案名稱,以遞迴比對任何項目(但無法在部分名稱旁邊)。The double wildcard (**) can also be used in place of folder or file names to match anything recursively (but it cannot be next to partial names). 例如,C:\MyGame\**\Level1\**可以選取 C:\MyGame\Audios\Level1\warp.mp3C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4For example, C:\MyGame\**\Level1\** can select C:\MyGame\Audios\Level1\warp.mp3 and C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4. 也可以使用萬用字元直接變更檔名,做為封裝程序的一部分,如果在來源和目的地之間的不同位置使用萬用字元。Wildcards can also be used to directly change file names as part of the packaging process if the wildcards are used in different places between the source and destination. 例如,SourcePathC:\MyGame\Audios\*DestinationPathSound\copy_*,可以選取 C:\MyGame\Audios\UI.mp3,使其在套件中顯示為Sound\copy_UI.mp3For example, having C:\MyGame\Audios\* for SourcePath and Sound\copy_* for DestinationPath can select C:\MyGame\Audios\UI.mp3 and have it appear in the package as Sound\copy_UI.mp3. 一般而言,單一萬用字元和雙重萬用字元的數目必須與單一File元素的SourcePathDestinationPath是相同。In general, the number of single wildcards and double wildcards must be the same for the SourcePath and DestinationPath of a single File element.

進階封裝配置範例Advanced packaging layout example

以下是更加複雜的封裝配置範例:Here's an example of a more complicated packaging layout:

<PackagingLayout xmlns="http://schemas.microsoft.com/appx/makeappx/2017">
  <!-- Main game -->
  <PackageFamily ID="MyGame" FlatBundle="true" ManifestPath="C:\mygame\appxmanifest.xml" ResourceManager="false">
    
    <!-- x64 code package-->
    <Package ID="x64" ProcessorArchitecture="x64">
      <Files>
        <File DestinationPath="*" SourcePath="C:\mygame\*"/>
        <File ExcludePath="*C:\mygame\*.txt"/>
      </Files>
    </Package>

    <!-- Media asset package -->
    <AssetPackage ID="Media" AllowExecution="false">
      <Files>
        <File DestinationPath="Media\**" SourcePath="C:\mygame\media\**"/>
      </Files>
    </AssetPackage>
    
    <!-- English resource package -->
    <ResourcePackage ID="en">
      <Files>
        <File DestinationPath="english\**" SourcePath="C:\mygame\english\**"/>
      </Files>
      <Resources Default="true">
        <Resource Language="en"/>
      </Resources>
    </ResourcePackage>

    <!-- French resource package -->
    <ResourcePackage ID="fr">
      <Files>
        <File DestinationPath="french\**" SourcePath="C:\mygame\french\**"/>
      </Files>
      <Resources>
        <Resource Language="fr"/>
      </Resources>
    </ResourcePackage>
  </PackageFamily>

  <!-- DLC in the related set -->
  <PackageFamily ID="DLC" Optional="true" ManifestPath="C:\DLC\appxmanifest.xml">
    <Package ID="DLC.x86" Architecture="x86">
      <Files>
        <File DestinationPath="**" SourcePath="C:\DLC\**"/>
      </Files>
    </Package>
  </PackageFamily>

  <!-- DLC not part of the related set -->
  <PackageFamily ID="Themes" Optional="true" RelatedSet="false" ManifestPath="C:\themes\appxmanifest.xml">
    <Package ID="Themes.main" Architecture="neutral">
      <Files>
        <File DestinationPath="**" SourcePath="C:\themes\**"/>
      </Files>
    </Package>
  </PackageFamily>

  <!-- Existing packages that need to be included/referenced in the bundle -->
  <PrebuiltPackage Path="C:\prebuilt\DLC2.appxbundle" />

</PackagingLayout>

此範例與簡單範例的差異在於加上ResourcePackageOptional元素。This example differs from the simple example with the addition of ResourcePackage and Optional elements.

您可以使用ResourcePackage元素指定資源套件。Resource packages can be specified with the ResourcePackage element. ResourcePackage內,Resources元素必須用來指定資源套件的資源限定元。Within the ResourcePackage, the Resources element must be used to specify the resource qualifiers of the resource pack. 資源限定元是資源套件支援的資源,這裡,我們可以看到定義了兩個資源套件,各別包含英文和法文特定的檔案。The resource qualifiers are the resources that are supported by the resource pack, here, we can see that there are two resource packs defined and they each contain the English and French specific files. 資源套件可以有多個限定元,可透過在Resources內新增另一個Resource元素來完成這個動作。A resource pack can have more than one qualifier, this can be done by adding another Resource element within Resources. 也必須指定資源維度的預設資源,如果維度存在(維度是 language、scale、dxfl)。A default resource for the resource dimension must also be specified if the dimension exists (dimensions being language, scale, dxfl). 這裡,我們會看見英文是預設語言,這表示,不需要設定法文系統語言的使用者,將改為下載英文資源套件並以英文顯示。Here, we can see that English is the default language, meaning that for users that does not have a system language of French set, they will fallback to downloading the English resource pack and display in English.

選用套件有自己不同的套件系列名稱,必須使用PackageFamily元素定義,同時將Optional屬性指定為trueOptional packages each have their own distinct package family names and must be defined with PackageFamily elements, while specifying the Optional attribute to be true. RelatedSet屬性用來指定選用套件是否在相關集合中(預設是 true)– 選用套件是否應該使用主要套件更新。The RelatedSet attribute is used to specify whether the optional package is within the related set (by default this is true) – whether the optional package should be updated with the primary package.

PrebuiltPackage元素是用來新增封裝配置中未定義的封裝,以在要建立的應用程式套件組合檔案中包含或參考。The PrebuiltPackage element is used to add packages that are not defined in the packaging layout to be included or referenced in the app bundle file(s) to be built. 在此情況下,這裡會包含另一個 DLC 選用套件,讓主要應用程式組合檔案可以參考它,並將它納入相關的集合中。In this case, another DLC optional package is being included here so that the primary app bundle file can reference it and have it be part of the related set.

使用封裝配置和 MakeAppx.exe 建置應用程式套件Build app packages with a packaging layout and MakeAppx.exe

一旦您的應用程式有封裝配置,您可以開始使用 MakeAppx.exe 建置應用程式的套件。Once you have the packaging layout for your app, you can start using MakeAppx.exe to build the packages of your app. 若要建置封裝配置中定義的所有套件,使用命令:To build all of the packages defined in the packaging layout, use the command:

MakeAppx.exe build /f PackagingLayout.xml /op OutputPackages\

不過,如果您要更新您的應用程式,並某些套件不包含任何變更的檔案,您可以只建置已變更的套件。But, if you are updating your app and some packages don't contain any changed files, you can build only the packages that have changed. 使用這個頁面上的簡單封裝配置範例和建置 x64 架構套件,我們的命令看起來如下:Using the simple packaging layout example on this page and building the x64 architecture package, this is what our command would look like:

MakeAppx.exe build /f PackagingLayout.xml /id "x64" /ip PreviousVersion\ /op OutputPackages\ /iv

/id旗標可以用來從封裝配置選取要建置的套件,對應於配置中的ID屬性。The /id flag can be used to select the packages to be built from the packaging layout, corresponding to the ID attribute in the layout. /ip用來表示上一版套件此時的位置。The /ip is used to indicate where the previous version of the packages are in this case. 必須提供舊版,因為應用程式套件組合檔案仍然需要參照舊版的媒體封裝。The previous version must be provided because the app bundle file still needs to reference the previous version of the Media package. /iv旗標用來自動增加建置套件版本 (而不在AppxManifest中變更版本)。The /iv flag is used to automatically increment the version of the packages being built (instead of changing the version in the AppxManifest). 或者,參數/pv/bv可分別用於直接提供套件版本(適用於所有要建立的套件)及套件組合版本(適用於所有要建立的套件組合)。Alternatively, the switches /pv and /bv can be used to directly provide a package version (for all packages to be created) and a bundle version (for all bundles to be created), respectively. 使用此頁面上的進階封裝配置範例,若只要建置Themes選用套件組合和它所參考的Themes.main應用程式套件,請使用此命令:Using the advanced packaging layout example on this page, if you want to only build the Themes optional bundle and the Themes.main app package that it references, you would use this command:

MakeAppx.exe build /f PackagingLayout.xml /id "Themes" /op OutputPackages\ /bc /nbp

/bc旗標用來表示Themes套件組合的子系也應該建置 (在這種情形下將建置Themes.main)。The /bc flag is used to denote that the children of the Themes bundle should also be built (in this case Themes.main will be built). /nbp旗標用來表示Themes套件組合的父系不應該建置。The /nbp flag is used to denote that the parent of the Themes bundle should not be built. Themes的父系是選用應用程式套件組合,為主要應用程式套件組合:MyGameThe parent of Themes, which is an optional app bundle, is the primary app bundle: MyGame. 通常對於相關集合中的選用套件,主要應用程式套件組合也必須建置,才能安裝選用套件,因為當選用套件在相關集合中時,主要應用程式套件組合中也會參照選用套件 (以確保主要和選用套件之間的版本)。Usually for an optional package in a related set, the primary app bundle must also be built for the optional package to be installable, since the optional package is also referenced in the primary app bundle when it is in a related set (to guarantee versioning between the primary and the optional packages). 下圖說明這些套件之間的父子關係:The parent child relationship between packages is illustrated in the following diagram:

封裝配置圖表