Création de package à l’aide de la disposition de mise en package

Avec l’introduction des packages d’actifs, les développeurs disposent désormais des outils permettant de générer davantage de packages en plus de types de packages. Lorsqu’une application devient plus grande et plus complexe, elle est souvent composée de plus de packages, et la difficulté de gérer ces packages augmente (en particulier si vous créez en dehors de Visual Studio et utilisez des fichiers de mappage). Pour simplifier la gestion de la structure d’empaquetage d’une application, vous pouvez utiliser la disposition d’empaquetage prise en charge par MakeAppx.exe.

La disposition d’empaquetage est un document XML unique qui décrit la structure d’empaquetage de l’application. Il spécifie les bundles d’une application (principale et facultative), les packages dans les bundles et les fichiers des packages. Les fichiers peuvent être sélectionnés à partir de différents dossiers, lecteurs et emplacements réseau. Les caractères génériques peuvent être utilisés pour sélectionner ou exclure des fichiers.

Une fois la disposition d’empaquetage d’une application configurée, elle est utilisée avec MakeAppx.exe pour créer tous les packages d’une application dans un seul appel de ligne de commande. La disposition de l’empaquetage peut être modifiée pour modifier la structure de package en fonction de vos besoins de déploiement.

Exemple de disposition d’empaquetage simple

Voici un exemple de disposition d’empaquetage simple :

<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>

Nous allons décomposer cet exemple pour comprendre son fonctionnement.

PackageFamily

Cette disposition d’empaquetage crée un fichier groupé d’application plat unique avec un package d’architecture x64 et un package de ressources « Media ».

L’élément PackageFamily est utilisé pour définir un bundle d’applications. Vous devez utiliser l’attribut ManifestPath pour fournir un AppxManifest pour le bundle. AppxManifest doit correspondre à AppxManifest pour le package d’architecture du bundle. L’attribut ID doit également être fourni. Il est utilisé avec MakeAppx.exe lors de la création du package afin que vous puissiez créer uniquement ce package si vous le souhaitez, et il s’agit du nom de fichier du package résultant. L’attribut FlatBundle est utilisé pour décrire le type de bundle que vous souhaitez créer, true pour un bundle plat (que vous pouvez en savoir plus ici) et false pour un bundle classique. L’attribut ResourceManager est utilisé pour spécifier si les packages de ressources de ce bundle utilisent MRT pour accéder aux fichiers. Cela est vrai par défaut, mais à partir de Windows 10, version 1803, ce n’est pas encore prêt. Cet attribut doit donc être défini sur false.

Package et AssetPackage

Dans PackageFamily, les packages contenus ou références de l’application sont définis. Ici, le package d’architecture (également appelé package principal) est défini avec l’élément Package et le package de ressources est défini avec l’élément AssetPackage . Le package d’architecture doit spécifier l’architecture pour laquelle le package est destiné, soit « x64 », « x86 », « arm » ou « neutral ». Vous pouvez également (éventuellement) fournir directement un AppxManifest spécifiquement pour ce package à l’aide de l’attribut ManifestPath à nouveau. Si un AppxManifest n’est pas fourni, celui-ci est généré automatiquement à partir de l’AppxManifest fourni pour PackageFamily.

Par défaut, AppxManifest est généré pour chaque package dans le bundle. Pour le package de ressources, vous pouvez également définir l’attribut AllowExecution . La définition de cette valeur sur false (valeur par défaut) vous aidera à réduire le temps de publication de votre application, car les packages qui n’ont pas besoin d’exécuter n’ont pas leur analyse antivirus bloquent le processus de publication (vous pouvez en savoir plus sur cela lors de l’introduction aux packages d’éléments multimédias).

Fichiers

Dans chaque définition de package, vous pouvez utiliser l’élément File pour sélectionner les fichiers à inclure dans ce package. L’attribut SourcePath est l’emplacement des fichiers localement. Vous pouvez sélectionner des fichiers à partir de différents dossiers (en fournissant des chemins relatifs), des lecteurs différents (en fournissant des chemins absolus) ou même des partages réseau (en fournissant quelque chose comme \\myshare\myapp\*). DestinationPath est l’endroit où les fichiers se retrouvent dans le package, par rapport à la racine du package. ExcludePath peut être utilisé (au lieu des deux autres attributs) pour sélectionner des fichiers à exclure des fichiers sélectionnés par les attributs SourcePath d’autres éléments file dans le même package.

Chaque élément File peut être utilisé pour sélectionner plusieurs fichiers à l’aide de caractères génériques. En général, un caractère générique unique (*) peut être utilisé n’importe où dans le chemin n’importe quel nombre de fois. Toutefois, un caractère générique unique correspond uniquement aux fichiers d’un dossier et non aux sous-dossiers. Par exemple, C:\MyGame\*\* peut être utilisé dans SourcePath pour sélectionner les fichiers C:\MyGame\Audios\UI.mp3 et C:\MyGame\Videos\intro.mp4, mais il ne peut pas sélectionner C:\MyGame\Audios\Level1\warp.mp3. Le caractère générique double (**) peut également être utilisé à la place de noms de dossiers ou de fichiers pour correspondre à tout ce qui est récursif (mais il ne peut pas être en regard des noms partiels). Par exemple, C:\MyGame\**\Level1\** peut sélectionner C:\MyGame\Audios\Level1\warp.mp3 et C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4. Les caractères génériques peuvent également être utilisés pour modifier directement les noms de fichiers dans le cadre du processus d’empaquetage si les caractères génériques sont utilisés à différents endroits entre la source et la destination. Par exemple, l’utilisation C:\MyGame\Audios\* de SourcePath et Sound\copy_* de DestinationPath peut sélectionner C:\MyGame\Audios\UI.mp3 et l’afficher dans le package en tant que Sound\copy_UI.mp3. En général, le nombre de caractères génériques uniques et de caractères génériques doubles doit être le même pour sourcePath et DestinationPath d’un seul élément File .

Exemple de disposition d’empaquetage avancée

Voici un exemple de disposition d’empaquetage plus complexe :

<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>

Cet exemple diffère de l’exemple simple avec l’ajout d’éléments ResourcePackage et Facultatifs .

Les packages de ressources peuvent être spécifiés avec l’élément ResourcePackage . Dans ResourcePackage, l’élément Resources doit être utilisé pour spécifier les qualificateurs de ressources du pack de ressources. Les qualificateurs de ressources sont les ressources prises en charge par le pack de ressources, ici, nous pouvons voir qu’il existe deux packs de ressources définis et qu’ils contiennent chacun les fichiers anglais et Français spécifiques. Un pack de ressources peut avoir plusieurs qualificateurs, cela peut être effectué en ajoutant un autre élément Resource dans Resources. Une ressource par défaut pour la dimension de ressource doit également être spécifiée si la dimension existe (dimensions en cours de langage, mise à l’échelle, dxfl). Ici, nous pouvons voir que l’anglais est la langue par défaut, ce qui signifie que pour les utilisateurs qui n’ont pas de langue système de Français défini, ils secours pour télécharger le pack de ressources anglais et afficher en anglais.

Les packages facultatifs ont chacun leurs propres noms de famille de packages distincts et doivent être définis avec les éléments PackageFamily , tout en spécifiant l’attribut Facultatif à true. L’attribut RelatedSet est utilisé pour spécifier si le package facultatif se trouve dans l’ensemble associé (par défaut, il s’agit de true) : si le package facultatif doit être mis à jour avec le package principal.

L’élément PrebuiltPackage permet d’ajouter des packages qui ne sont pas définis dans la disposition d’empaquetage à inclure ou à référencer dans le ou les fichiers de bundle d’applications à générer. Dans ce cas, un autre package facultatif DLC est inclus ici afin que le fichier de bundle d’application principal puisse le référencer et qu’il fasse partie de l’ensemble associé.

Créer des packages d’application avec une disposition d’empaquetage et MakeAppx.exe

Une fois que vous disposez de la disposition d’empaquetage pour votre application, vous pouvez commencer à utiliser MakeAppx.exe pour générer les packages de votre application. Pour générer tous les packages définis dans la disposition d’empaquetage, utilisez la commande :

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

Toutefois, si vous mettez à jour votre application et que certains packages ne contiennent aucun fichier modifié, vous pouvez générer uniquement les packages qui ont changé. À l’aide de l’exemple de disposition d’empaquetage simple sur cette page et de la création du package d’architecture x64, voici à quoi ressemble notre commande :

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

L’indicateur /id peut être utilisé pour sélectionner les packages à générer à partir de la disposition de l’empaquetage, correspondant à l’attribut ID de la disposition. Il /ip est utilisé pour indiquer où se trouvent la version précédente des packages. La version précédente doit être fournie, car le fichier de bundle d’applications doit toujours référencer la version précédente du package Media . L’indicateur /iv est utilisé pour incrémenter automatiquement la version des packages générés (au lieu de modifier la version dans AppxManifest). Vous pouvez également utiliser les commutateurs /pv et /bv être utilisés pour fournir directement une version de package (pour tous les packages à créer) et une version groupée (pour tous les bundles à créer), respectivement. À l’aide de l’exemple de mise en page d’empaquetage avancée sur cette page, si vous souhaitez uniquement générer le bundle facultatif Thèmes et le package d’application Themes.main référencé, vous devez utiliser cette commande :

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

L’indicateur /bc est utilisé pour indiquer que les enfants de l’ensemble de thèmes doivent également être générés (dans ce cas Themes.main sera généré). L’indicateur /nbp est utilisé pour indiquer que le parent de l’ensemble de thèmes ne doit pas être généré. Le parent des thèmes, qui est un bundle d’applications facultatif, est le bundle d’applications principal : MyGame. En règle générale, pour un package facultatif dans un ensemble associé, le bundle d’application principal doit également être généré pour que le package facultatif soit installable, car le package facultatif est également référencé dans le bundle d’applications principal lorsqu’il se trouve dans un ensemble associé (pour garantir le contrôle de version entre le package principal et les packages facultatifs). La relation enfant parente entre les packages est illustrée dans le diagramme suivant :

Packaging Layout Diagram