Создание пакета с макетом упаковки

Благодаря внедрению пакетов ресурсов разработчики теперь имеют средства для создания дополнительных пакетов в дополнение к дополнительным типам пакетов. Так как приложение становится более большим и более сложным, он часто будет состоять из большего количества пакетов, и сложность управления этими пакетами увеличится (особенно если вы создаете вне Visual Studio и используете файлы сопоставления). Чтобы упростить управление структурой упаковки приложения, можно использовать макет упаковки, поддерживаемый MakeAppx.exe.

Макет упаковки — это один XML-документ, описывающий структуру упаковки приложения. Он задает пакеты приложения (основной и необязательный), пакеты в пакетах и файлы в пакетах. Файлы можно выбрать из разных папок, дисков и сетевых расположений. Подстановочные знаки можно использовать для выбора или исключения файлов.

После настройки макета упаковки для приложения он используется вместе с MakeAppx.exe для создания всех пакетов для приложения одним командным вызовом. Макет упаковки можно изменить, чтобы изменить структуру пакета в соответствии с потребностями развертывания.

Пример простого макета упаковки

Ниже приведен пример того, как выглядит простой макет упаковки:

<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 и пакетом ресурсов «Media».

Элемент PackageFamily используется для определения пакета приложений. Атрибут ManifestPath необходимо использовать для указания AppxManifest для пакета, AppxManifest должен соответствовать AppxManifest для архитектурного пакета этого набора. Атрибут идентификатора также должен быть предоставлен. Это используется с MakeAppx.exe во время создания пакета, чтобы можно было создать только этот пакет, если вы хотите этого, а это будет именем файла результирующего пакета. Атрибут FlatBundle используется для описания типа пакета, который требуется создать, true для плоского пакета (который можно узнать здесь) и false для классического пакета. Атрибут ResourceManager используется для указания того, будут ли пакеты ресурсов в этом пакете использовать MRT для доступа к файлам. По умолчанию это значение true, но по состоянию на Windows 10 версии 1803 это еще не готово, поэтому этот атрибут должен иметь значение false.

Пакет и Asset-пакет

В PackageFamily определены пакеты, которые содержит или на которые ссылается пакет приложений. Здесь пакет архитектуры (также называемый основным пакетом) определяется элементом Package , а пакет активов определяется элементом AssetPackage . Пакет архитектуры должен указать, для какой архитектуры предназначен пакет либо x64, x86, либо "arm", либо "нейтральный". Вы также можете (необязательно) напрямую предоставить AppxManifest специально для этого пакета с помощью атрибута ManifestPath еще раз. Если appxManifest не указан, он будет автоматически создан из AppxManifest , предоставленного для PackageFamily.

По умолчанию для каждого пакета в составе пакета будет создан AppxManifest. Для пакета активов можно также задать атрибут AllowExecution . Если установить значение false (по умолчанию), это будет способствовать сокращению времени публикации вашего приложения, так как пакеты, которые не требуют выполнения, не будут замедлять процесс публикации из-за проверки на вирусы (дополнительные сведения об этом см. в статье «Введение в пакеты ресурсов»).

Файлы

В каждом определении пакета можно использовать элемент File для выбора файлов для включения в этот пакет. Атрибут SourcePath — это место локального расположения файлов. Вы можете выбирать файлы из разных папок (предоставляя относительные пути), разные диски (предоставляя абсолютные пути) или даже сетевые ресурсы (предоставляя что-то подобное \\myshare\myapp\*). DestinationPath — это место, где файлы будут входить в пакет относительно корневого каталога пакета. ExcludePath можно использовать (вместо других двух атрибутов) для выбора файлов, которые должны быть исключены из файлов, выбранных атрибутами SourcePath других элементов File в одном пакете.

Каждый элемент File можно использовать для выбора нескольких файлов с помощью подстановочных знаков. Как правило, один подстановочный знак (*) можно использовать в любом месте пути в любое количество раз. Однако один подстановочный знак будет соответствовать только файлам в папке, а не в вложенных папках. Например, C:\MyGame\*\* можно использовать в SourcePath для выбора файлов C:\MyGame\Audios\UI.mp3 и C:\MyGame\Videos\intro.mp4, но он не может выбрать 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 может привести к выбору C:\MyGame\Audios\UI.mp3 и его отображению в пакете как Sound\copy_UI.mp3. Как правило, количество отдельных подстановочных знаков и двойных подстановочных знаков должно быть одинаковым для Элемента SourcePath и DestinationPath одного элемента File .

Пример макета расширенной упаковки

Ниже приведен пример более сложного макета упаковки:

<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 и Необязательных элементов.

Пакеты ресурсов можно указать с помощью элемента ResourcePackage . В ResourcePackage элемент Resources должен использоваться для указания квалификаторов ресурсов пакета ресурсов. Квалификаторы ресурсов — это ресурсы, поддерживаемые пакетом ресурсов, здесь мы видим, что определены два пакета ресурсов, и каждый из них содержит файлы на английском и французском языках. Пакет ресурсов может иметь несколько квалификаторов; это можно сделать, добавив другой элемент Resource в Resources. Ресурс по умолчанию для измерения также должен быть указан, если измерение существует (например, это может быть языковое, масштабное или dxfl измерение). Здесь мы видим, что английский язык является языком по умолчанию, то есть для пользователей, у которых система не настроена на французский, будет загружен пакет ресурсов на английском языке.

Необязательные пакеты имеют собственные имена семейств пакетов и должны быть определены с помощью элементов PackageFamily с указанием значения атрибута Optional в true. Атрибут RelatedSet используется для указания того, находится ли необязательный пакет в связанном наборе (по умолчанию это верно) — следует ли обновить необязательный пакет с основным пакетом.

Элемент 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 можно использовать для выбора пакетов, которые необходимо создать из макета упаковки, соответствующего атрибуту идентификатора в макете. Используется /ip для указания того, где в данном случае находится предыдущая версия пакетов. Предыдущая версия должна быть предоставлена, так как файл пакета приложений по-прежнему должен ссылаться на предыдущую версию пакета мультимедиа . Флаг /iv используется для автоматического увеличения версии создаваемых пакетов (вместо изменения версии в AppxManifest). Кроме того, коммутаторы /pv и /bv могут использоваться для прямого предоставления версии пакета (для всех пакетов, которые необходимо создать) и версии пакета (для всех создаваемых пакетов) соответственно. Используя пример макета расширенной упаковки на этой странице, если вы хотите создать только необязательный пакет тем и пакет приложения Themes.main , который он ссылается, используйте следующую команду:

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

Флаг /bc используется для обозначения того, что дочерние элементы пакета тем также должны быть созданы (в данном случае Темы.main будут созданы). Флаг /nbp используется для обозначения того, что родительский элемент пакета тем не должен быть создан. Основным пакетом приложений является MyGame, которому принадлежит необязательный пакет приложений Тем. Обычно для дополнительного пакета в связанном наборе основной пакет приложений также должен быть создан для установки необязательного пакета, так как необязательный пакет также ссылается на основной пакет приложений, если он находится в связанном наборе (чтобы гарантировать управление версиями между основными и необязательными пакетами). Иерархические отношения между пакетами показаны на схеме ниже.

Схема макета упаковки