Paketerstellung mit dem Verpackungslayout

Mit der Einführung von Bestandspaketen verfügen Entwickler jetzt über die Tools zum Erstellen weiterer Pakete zusätzlich zu weiteren Pakettypen. Da eine App größer und komplexer wird, wird es häufig aus weiteren Paketen bestehen, und die Schwierigkeiten beim Verwalten dieser Pakete werden erhöht (insbesondere, wenn Sie außerhalb von Visual Studio erstellen und Zuordnungsdateien verwenden). Um die Verwaltung der Verpackungsstruktur einer App zu vereinfachen, können Sie das von MakeAppx.exe unterstützte Verpackungslayout verwenden.

Das Verpackungslayout ist ein einzelnes XML-Dokument, das die Verpackungsstruktur der App beschreibt. Es gibt die Bündel einer App (primär und optional), die Pakete in den Bündeln und die Dateien in den Paketen an. Dateien können aus verschiedenen Ordnern, Laufwerken und Netzwerkspeicherorten ausgewählt werden. Wildcards können verwendet werden, um Dateien auszuwählen oder auszuschließen.

Nachdem das Verpackungslayout für eine App eingerichtet wurde, wird es mit MakeAppx.exe verwendet, um alle Pakete für eine App in einem einzigen Befehlszeilenaufruf zu erstellen. Das Verpackungslayout kann bearbeitet werden, um die Paketstruktur so zu ändern, dass sie ihren Bereitstellungsanforderungen entspricht.

Einfaches Verpackungslayoutbeispiel

Hier sehen Sie ein Beispiel dafür, wie ein einfaches Verpackungslayout aussieht:

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

Lassen Sie uns dieses Beispiel aufbrechen, um zu verstehen, wie es funktioniert.

PackageFamily

Dieses Paketlayout erstellt eine einzelne flache App-Paketdatei mit einem x64-Architekturpaket und einem "Media"-Objektpaket.

Das PackageFamily-Element wird verwendet, um ein App-Bundle zu definieren. Sie müssen das ManifestPath-Attribut verwenden, um ein AppxManifest für das Bundle bereitzustellen, das AppxManifest sollte dem AppxManifest für das Architekturpaket des Bundles entsprechen. Das ID-Attribut muss ebenfalls bereitgestellt werden. Dies wird bei der Paketerstellung mit MakeAppx.exe verwendet, sodass Sie nur dieses Paket erstellen können, wenn Sie möchten, und dies ist der Dateiname des resultierenden Pakets. Das FlatBundle-Attribut wird verwendet, um zu beschreiben, welche Art von Bundle Sie erstellen möchten, true für ein flaches Bündel (das Sie hier lesen können) und false für ein klassisches Bundle. Das ResourceManager-Attribut wird verwendet, um anzugeben, ob die Ressourcenpakete in diesem Bundle MRT verwenden, um auf die Dateien zuzugreifen. Dies ist standardmäßig wahr, aber ab Windows 10, Version 1803, ist dies noch nicht bereit, daher muss dieses Attribut auf "false" festgelegt werden.

Package and AssetPackage

Innerhalb der PackageFamily werden die Pakete, die das App-Bundle enthält, oder Verweise definiert. Hier wird das Architekturpaket (auch als Hauptpaket bezeichnet) mit dem Package-Element definiert, und das Objektpaket wird mit dem AssetPackage-Element definiert. Das Architekturpaket muss angeben, für welche Architektur das Paket verwendet wird, entweder "x64", "x86", "arm" oder "neutral". Sie können auch (optional) ein AppxManifest speziell für dieses Paket bereitstellen, indem Sie das ManifestPath-Attribut erneut verwenden. Wenn kein AppxManifest bereitgestellt wird, wird eine automatisch aus dem appxManifest generiert, das für das PackageFamily bereitgestellt wird.

Standardmäßig wird appxManifest für jedes Paket innerhalb des Bundles generiert. Für das Objektpaket können Sie auch das AllowExecution-Attribut festlegen. Wenn Sie dies auf "false " festlegen (standard), können Sie die Veröffentlichungszeit für Ihre App verringern, da Pakete, die nicht ausgeführt werden müssen, den Veröffentlichungsprozess nicht blockieren (Weitere Informationen finden Sie unter Einführung in Asset-Pakete).

Dateien

In jeder Paketdefinition können Sie das Dateielement verwenden, um Dateien auszuwählen, die in diesem Paket enthalten sind. Das SourcePath-Attribut ist der Ort, an dem sich die Dateien lokal befinden. Sie können Dateien aus unterschiedlichen Ordnern (indem Sie relative Pfade bereitstellen), unterschiedliche Laufwerke (indem Sie absolute Pfade bereitstellen) oder sogar Netzwerkfreigaben (z. B. bereitstellen) \\myshare\myapp\*auswählen. ZielPath ist der Ort, an dem die Dateien innerhalb des Pakets enden, relativ zum Paketstamm. ExcludePath kann verwendet werden (anstelle der anderen beiden Attribute), um Dateien auszuwählen, die von den SourcePath-Attributen anderer Dateielemente innerhalb desselben Pakets ausgeschlossen werden sollen.

Jedes Dateielement kann verwendet werden, um mehrere Dateien mithilfe von Wildcards auszuwählen. Im Allgemeinen können einzelne Wildcards (*) überall innerhalb des Pfads beliebig oft verwendet werden. Ein einzelner Wildcard entspricht jedoch nur den Dateien in einem Ordner und nicht mit Unterordnern. Beispielsweise kann in SourcePath verwendet werden, C:\MyGame\*\* um die Dateien C:\MyGame\Audios\UI.mp3 auszuwählen und C:\MyGame\Videos\intro.mp4, aber es kann nicht ausgewählt werdenC:\MyGame\Audios\Level1\warp.mp3. Der doppelte Platzhalter (**) kann auch anstelle von Ordner- oder Dateinamen verwendet werden, um etwas rekursiv abzugleichen (aber es kann nicht neben Teilnamen sein). Sie können z. B. C:\MyGame\**\Level1\** auswählen C:\MyGame\Audios\Level1\warp.mp3 und C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4. Platzhalter können auch verwendet werden, um Dateinamen im Rahmen des Verpackungsvorgangs direkt zu ändern, wenn die Platzhalter an verschiedenen Stellen zwischen der Quelle und dem Ziel verwendet werden. Beispielsweise können SourcePathC:\MyGame\Audios\* und Sound\copy_*DestinationPath auswählen C:\MyGame\Audios\UI.mp3 und im Paket Sound\copy_UI.mp3als angezeigt werden. Im Allgemeinen muss die Anzahl einzelner Wildcards und doppelter Wildcards für das SourcePath- und DestinationPath-Element eines einzelnen Dateielements identisch sein.

Beispiel für erweitertes Verpackungslayout

Hier ist ein Beispiel für ein komplizierteres Verpackungslayout:

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

In diesem Beispiel unterscheidet sich das einfache Beispiel mit dem Hinzufügen von ResourcePackage - und Optional-Elementen .

Ressourcenpakete können mit dem ResourcePackage-Element angegeben werden. Innerhalb des ResourcePackage muss das Resources-Element verwendet werden, um die Ressourcenqualifizierer des Ressourcenpakets anzugeben. Die Ressourcenqualifizierer sind die Ressourcen, die vom Ressourcenpaket unterstützt werden, hier sehen wir, dass zwei Ressourcenpakete definiert sind und sie jeweils die englischen und französischen spezifischen Dateien enthalten. Ein Ressourcenpaket kann mehrere Qualifizierer haben, dies kann durch Hinzufügen eines anderen Ressourcenelements innerhalb von Resources erfolgen. Eine Standardressource für die Ressourcendimension muss auch angegeben werden, wenn die Dimension vorhanden ist (Dimensionen wie Sprache, Skalierung, DXFL). Hier sehen wir, dass Englisch die Standardsprache ist, d. h. für Benutzer, die keine Systemsprache französisch festgelegt haben, werden sie zurückgesetzt, um das englische Ressourcenpaket herunterzuladen und in Englisch anzuzeigen.

Optionale Pakete weisen jeweils eigene eindeutige Paketfamiliennamen auf und müssen mit PackageFamily-Elementen definiert werden, während das optionale Attribut wahr sein soll. Das RelatedSet-Attribut wird verwendet, um anzugeben, ob sich das optionale Paket im verwandten Satz befindet (standardmäßig ist dies wahr) – ob das optionale Paket mit dem primären Paket aktualisiert werden soll.

Das PrebuiltPackage-Element wird verwendet, um Pakete hinzuzufügen, die nicht im Verpackungslayout definiert sind, um in die zu erstellenden App-Bundledatei(n) eingeschlossen oder darauf verwiesen zu werden. In diesem Fall wird ein weiteres optionales DLC-Paket hier enthalten, damit die primäre App-Bündeldatei darauf verweisen kann und teil des zugehörigen Satzes ist.

Erstellen von App-Paketen mit einem Verpackungslayout und MakeAppx.exe

Sobald Sie über das Verpackungslayout für Ihre App verfügen, können Sie mit MakeAppx.exe beginnen, um die Pakete Ihrer App zu erstellen. Verwenden Sie den Befehl, um alle im Verpackungslayout definierten Pakete zu erstellen:

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

Wenn Sie Jedoch Ihre App aktualisieren und einige Pakete keine geänderten Dateien enthalten, können Sie nur die Pakete erstellen, die geändert wurden. Mithilfe des einfachen Paketlayouts auf dieser Seite und dem Erstellen des x64-Architekturpakets würde unser Befehl aussehen:

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

Das /id Flag kann verwendet werden, um die Pakete auszuwählen, die aus dem Verpackungslayout erstellt werden sollen, das dem ID-Attribut im Layout entspricht. Dies /ip wird verwendet, um anzugeben, wo sich die vorherige Version der Pakete in diesem Fall befindet. Die vorherige Version muss bereitgestellt werden, da die App-Bundledatei weiterhin auf die vorherige Version des Medienpakets verweisen muss. Das /iv Flag wird verwendet, um die Version der zu erstellenden Pakete automatisch zu erhöhen (anstatt die Version im AppxManifest zu ändern). Alternativ können die Schalter /pv und /bv verwendet werden, um direkt eine Paketversion (für alle zu erstellenden Pakete) und eine Bundleversion (für alle zu erstellenden Bundles) bereitzustellen. Verwenden Sie das Beispiel für das erweiterte Verpackungslayout auf dieser Seite, wenn Sie nur das optionale Bundle "Designs " und das darauf verweisende Designs.Main-App-Paket erstellen möchten, verwenden Sie diesen Befehl:

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

Das /bc Flag wird verwendet, um anzugeben, dass die untergeordneten Elemente des Designs-Bundles auch erstellt werden sollen (in diesem Fall wird Designs.main erstellt). Das /nbp Flag wird verwendet, um anzugeben, dass das übergeordnete Element des Designs-Bundles nicht erstellt werden soll. Das übergeordnete Element von Designs, das ein optionales App-Bündel ist, ist das primäre App-Bundle: MyGame. Normalerweise muss das primäre App-Bundle für ein optionales Paket in einem verwandten Satz erstellt werden, damit das optionale Paket installiert werden kann, da das optionale Paket auch im primären App-Bundle referenziert wird, wenn es sich in einem verwandten Satz befindet (um die Versionsverwaltung zwischen den primären und den optionalen Paketen zu gewährleisten). Die Beziehung zwischen den übergeordneten untergeordneten Paketen wird im folgenden Diagramm veranschaulicht:

Packaging Layout Diagram