パッケージ レイアウトを使ったパッケージの作成

アセット パッケージの導入に伴い、開発者は、パッケージの種類に加えて、より多くのパッケージをビルドするためのツールを利用できるようになりました。 アプリが大きくなり複雑になるにつれて、多くの場合、より多くのパッケージで構成され、これらのパッケージを管理する難しさが増します (特に、Visual Studio の外部でビルドし、マッピング ファイルを使用している場合)。 アプリのパッケージ構造の管理を簡略化するために、MakeAppx.exe でサポートされているパッケージ レイアウトを使用できます。

パッケージ レイアウトは、アプリのパッケージ構造を記述する単一の XML ドキュメントです。 アプリ (プライマリとオプション) のバンドル、バンドル内のパッケージ、パッケージ内のファイルを指定します。 ファイルは、さまざまなフォルダー、ドライブ、ネットワークの場所から選択できます。 ワイルドカードを使用して、ファイルを選択または除外できます。

アプリのパッケージ レイアウトを設定した後、MakeAppx.exe と共に使用して、1 つのコマンド ライン呼び出しでアプリのすべてのパッケージを作成します。 パッケージ レイアウトを編集して、デプロイのニーズに合わせてパッケージ構造を変更できます。

シンプルなパッケージ レイアウトの例

単純なパッケージ レイアウトの例を次に示します。

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

この例を分解して、そのしくみを理解しましょう。

PackageFamily

このパッケージ レイアウトでは、x64 アーキテクチャ パッケージと "メディア" アセット パッケージを含む 1 つのフラットなアプリ バンドル ファイルが作成されます。

PackageFamily 要素は、アプリ バンドルを定義するために使用されます。 ManifestPath 属性を使用してバンドルの AppxManifest を指定する必要があります。AppxManifest は、バンドルのアーキテクチャ パッケージの AppxManifest に対応する必要があります。 ID 属性も指定する必要があります。 これはパッケージの作成時に MakeAppx.exe と共に使用されるため、必要に応じてこのパッケージのみを作成でき、結果のパッケージのファイル名になります。 FlatBundle 属性は、作成するバンドルの種類を記述するために使用され、フラット バンドルの場合は true (ここで詳しく読むことができます)、クラシック バンドルの場合は false を記述します。 ResourceManager 属性は、このバンドル内のリソース パッケージがファイルにアクセスするために MRT を使用するかどうかを指定するために使用されます。 これは既定では true ですが、Windows 10 バージョン 1803 の時点では、これはまだ準備ができていないため、この属性を false に設定する必要があります。

Package と AssetPackage

PackageFamily 内では、アプリ バンドルに含まれるパッケージまたは参照が定義されます。 ここでは、アーキテクチャ パッケージ (メイン パッケージとも呼ばれます) は Package 要素で定義され、アセット パッケージは AssetPackage 要素で定義されます。 アーキテクチャ パッケージでは、パッケージの対象となるアーキテクチャ ("x64"、"x86"、"arm"、"neutral" のいずれか) を指定する必要があります。 必要に応じて、ManifestPath 属性をもう 一度使用して、このパッケージ専用の AppxManifest直接指定 することもできます。 AppxManifest が指定されていない場合、PackageFamily 用提供された AppxManifest から自動的に生成されます。

既定では、 AppxManifest はバンドル内のすべてのパッケージに対して生成されます。 資産パッケージの場合は、AllowExecution 属性を設定することもできます。 これを false (既定値) に設定すると、実行する必要のないパッケージでウイルス スキャンによって発行プロセスがブロックされないため、アプリの発行時間が短縮されます (詳細については、資産パッケージの概要を参照してください)。

ファイル

各パッケージ定義内で、File 要素を使用して、このパッケージに含めるファイルを選択できます。 SourcePath 属性は、ファイルがローカルにある場所です。 異なるフォルダーからファイルを選択できます (相対パスを指定する)、異なるドライブ (絶対パスを指定することによって)、またはネットワーク共有 (次のようなもの \\myshare\myapp\*を提供することによって)。 DestinationPath は、パッケージ ルートを基準にして、ファイルがパッケージ内で終了する場所です。 ExcludePath は、(他の 2 つの属性ではなく) 使用して、同じパッケージ内の他の File 要素の SourcePath 属性によって選択されたファイルから除外されるファイルを選択するために使用できます。

File 要素を使用して、ワイルドカードを使用して複数のファイルを選択できます。 一般に、単一の wildカード (*) は、パス内の任意の場所で何度でも使用できます。 ただし、1 つのワイルドカードはフォルダー内のファイルにのみ一致し、サブフォルダーは一致しません。 たとえば、 C:\MyGame\*\* SourcePath でファイルC:\MyGame\Videos\intro.mp4C:\MyGame\Audios\UI.mp3選択するために使用できますが、選択C:\MyGame\Audios\Level1\warp.mp3することはできません。 二重ワイルドカード (**) は、フォルダー名またはファイル名の代わりに使用して、再帰的に何かを照合することもできます (ただし、部分名の横にすることはできません)。 たとえば、次の C:\MyGame\**\Level1\** コマンドを選択 C:\MyGame\Audios\Level1\warp.mp3 できます C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4。 ワイルドカードを使用して、ソースと宛先の異なる場所で野生のカードが使用されている場合は、パッケージ化プロセスの一環としてファイル名を直接変更することもできます。 たとえば、C:\MyGame\Audios\*SourcePath と Sound\copy_* DestinationPath を使用すると、パッケージ内で次のようにSound\copy_UI.mp3選択C:\MyGame\Audios\UI.mp3して表示できます。 一般に、単一のワイルドカードとダブル ワイルドカードの数は、1 つの File 要素の SourcePath と DestinationPath で同じである必要があります。

高度なパッケージ レイアウトの例

より複雑なパッケージ レイアウトの例を次に示します。

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

この例は、ResourcePackage 要素と Optional 要素を追加した単純な例とは異なります。

リソース パッケージは、ResourcePackage 要素で指定できます。 ResourcePackage 内では、リソース パックのリソース修飾子を指定するために Resources 要素を使用する必要があります。 リソース修飾子はリソース パックでサポートされているリソースです。ここでは、2 つのリソース パックが定義されており、それぞれに英語とフランス語の特定のファイルが含まれていることがわかります。 リソース パックには複数の修飾子を含めることができます。これを行うには、Resourcesに別の Resource 要素を追加します。 ディメンションが存在する場合は、リソース ディメンションの既定のリソースも指定する必要があります (ディメンションは言語、スケール、dxfl)。 ここでは、英語が既定の言語であることがわかります。つまり、フランス語のシステム言語を持たないユーザーの場合は、英語リソース パックのダウンロードにフォールバックし、英語で表示されます。

省略可能なパッケージはそれぞれ独自のパッケージ ファミリ名を持ち、PackageFamily 要素で定義する必要があります。一方で、Optional 属性を true に指定する必要があります。 RelatedSet 属性は、オプション パッケージが関連セット内にあるかどうかを指定するために使用されます (既定では true です)。オプション パッケージをプライマリ パッケージで更新するかどうかを指定します。

PrebuiltPackage 要素は、ビルドするアプリ バンドル ファイルに含めるか参照する必要があるがパッケージ レイアウトで定義されていないパッケージを追加するために使用されます。 この場合、ここで別の DLC オプション パッケージを追加することにより、プライマリ アプリ バンドル ファイルが参照し、関連するセットの一部とすることができるようにします。

パッケージ レイアウトと MakeAppx.exe を使用してアプリ パッケージをビルドする

アプリのパッケージ レイアウトを作成したら、MakeAppx.exe を使用してアプリのパッケージをビルドできます。 パッケージ レイアウトで定義されているすべてのパッケージをビルドするには、次のコマンドを使用します。

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

ただし、アプリを更新していて、一部のパッケージに変更されたファイルが含まれていない場合は、変更されたパッケージのみをビルドできます。 このページの単純なパッケージ レイアウトの例を使用して x64 アーキテクチャ パッケージをビルドすると、コマンドは次のようになります。

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

この/idフラグを使用して、レイアウト内の ID 属性に対応するパッケージ レイアウトからビルドするパッケージを選択できます。 この /ip 場合、以前のバージョンのパッケージがどこにあるかを示すために使用されます。 アプリ バンドル ファイルは引き続き Media パッケージの以前のバージョンを参照する必要があるため、以前のバージョンを指定する必要があります。 この/ivフラグは、ビルドされているパッケージのバージョンを自動的にインクリメントするために使用されます (AppxManifestバージョンを変更する代わりに)。 または、スイッチ/pv/bvを使用して、パッケージ バージョン (作成するすべてのパッケージ用) とバンドル バージョン (作成するすべてのバンドル用) をそれぞれ直接提供できます。 このページの高度なパッケージ レイアウトの例を使用して、Themes オプション バンドルと、それが参照する Themes.メイン アプリ パッケージのみをビルドする場合は、次のコマンドを使用します。

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

フラグは/bc、Themes バンドルの子もビルドする必要があることを示すために使用されます (この場合、Themes.メイン がビルドされます)。 フラグは/nbp、Themes バンドルの親をビルドしないことを示すために使用されます。 オプションのアプリ バンドルである Themes親は、プライマリ アプリ バンドル MyGame です。 通常、関連セット内の省略可能なパッケージの場合、オプション のパッケージがインストールできるようにプライマリ アプリ バンドルもビルドする必要があります。これは、関連セット内にある場合 (プライマリ パッケージとオプション パッケージの間のバージョン管理を保証するため) に、オプション パッケージもプライマリ アプリ バンドルで参照されるためです。 パッケージ間の親子関係を次の図に示します。

Packaging Layout Diagram