Поделиться через


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

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

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

После настройки макета упаковки для приложения он используется с 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.

Пакет и AssetPackage

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

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

Files

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

Каждый элемент File можно использовать для выбора нескольких файлов с помощью wild карта s. Как правило, один дикий карта (*) можно использовать в любом месте пути любое количество раз. Однако один дикий карта будет соответствовать только файлам в папке, а не к вложенным папкам. Например, 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 , указывая атрибут "Необязательный " для значения 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. Обычно для дополнительного пакета в связанном наборе основной пакет приложений также должен быть создан для установки необязательного пакета, так как необязательный пакет также ссылается на основной пакет приложений, если он находится в связанном наборе (чтобы гарантировать управление версиями между основными и необязательными пакетами). Связь родительского дочернего элемента между пакетами показана на следующей схеме:

Packaging Layout Diagram