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

Avec l’introduction des packages d’éléments multimédias, les développeurs disposent désormais des outils permettant de créer davantage de packages en plus de types de packages. À mesure qu’une application devient plus grande et plus complexe, elle sera souvent composée de plus de packages, et la difficulté de gérer ces packages augmente (en particulier si vous générez 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 regroupements et les fichiers dans les packages. Les fichiers peuvent être sélectionnés à partir de différents dossiers, lecteurs et emplacements réseau. Les carte 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 appel de ligne de commande unique. La disposition d’empaquetage peut être modifiée pour modifier la structure du 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’applications plat unique avec un package d’architecture x64 et un package d’éléments multimédias « Media ».

L’élément PackageFamily est utilisé pour définir un ensemble d’applications. Vous devez utiliser l’attribut ManifestPath pour fournir un AppxManifest pour le bundle, appxManifestdoit correspondre à AppxManifest pour le package d’architecture du bundle. L’attribut ID doit également être fourni. Cela est utilisé avec MakeAppx.exe lors de la création du package afin de pouvoir 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 d’offre groupée 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 depuis 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 que le bundle d’application contient ou références 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, il est automatiquement généré à partir de l’AppxManifest fourni pour PackageFamily.

Par défaut, AppxManifest sera généré pour chaque package au sein de l’offre groupée. 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) permet de réduire le temps de publication de votre application, car les packages qui n’ont pas besoin d’être exécutés n’auront pas de blocage de l’analyse du virus dans le processus de publication (vous pouvez en savoir plus sur cela lors de l’introduction aux packages de ressources).

Fichiers

Dans chaque définition de package, vous pouvez utiliser l’élément File pour sélectionner des fichiers à inclure dans ce package. L’attribut SourcePath est l’emplacement où les fichiers sont localement. Vous pouvez sélectionner des fichiers à partir de différents dossiers (en fournissant des chemins d’accès relatifs), différents lecteurs (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 terminent 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 de fichier 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 carte s. En général, un caractère sauvage unique (carte) peut* être utilisé n’importe où dans le chemin d’accès à un nombre quelconque de fois. Toutefois, un caractère générique unique carte correspond uniquement aux fichiers d’un dossier et non pas aux sous-dossiers. Par exemple, C:\MyGame\*\* vous pouvez l’utiliser dans Le Chemin Source pour sélectionner les fichiers C:\MyGame\Audios\UI.mp3 et C:\MyGame\Videos\intro.mp4, mais il ne peut pas le sélectionner C:\MyGame\Audios\Level1\warp.mp3. Le double caractère générique carte (**) 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\** vous pouvez sélectionner C:\MyGame\Audios\Level1\warp.mp3 et C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4. Les carte génériques peuvent également être utilisées pour modifier directement les noms de fichiers dans le cadre du processus d’empaquetage si les caractères génériques carte sont utilisés à différents endroits entre la source et la destination. Par exemple, avoir C:\MyGame\Audios\* pour SourcePath et Sound\copy_*destinationPath peut sélectionner C:\MyGame\Audios\UI.mp3 et l’afficher dans le package en tant que Sound\copy_UI.mp3. En règle générale, le nombre de caractères génériques uniques carte s et les doubles caractères génériques carte doivent être identiques pour sourcePath et DestinationPath d’un seul élément File.

Exemple de disposition d’empaquetage avancé

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 ressource 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 des fichiers 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 ne disposent pas d’une langue système de Français définie, ils seront de secours pour télécharger le pack de ressources anglais et s’afficher en anglais.

Les packages facultatifs ont chacun leurs propres noms de famille de packages distincts et doivent être définis avec des é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 cela est vrai) : si le package facultatif doit être mis à jour avec le package principal.

L’élément PrebuiltPackage est utilisé pour 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’application à générer. Dans ce cas, un autre package facultatif DLC est inclus ici afin que le fichier d’offre groupée d’applications principale 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 avez 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 mise en page 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 d’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 groupé 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). Les commutateurs /pv et /bv peuvent également être utilisés pour fournir directement une version de package (pour que tous les packages soient créés) et une version groupée (pour que tous les bundles soient créés), respectivement. À l’aide de l’exemple de mise en page d’empaquetage avancé sur cette page, si vous souhaitez uniquement générer le bundle facultatif Thèmes et le package d’application Themes.main qu’il référence, vous utilisez 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’offre groupée 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 du bundle Thèmes ne doit pas être généré. Le parent des thèmes, qui est un bundle d’applications facultatif, est le groupe 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 groupe 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