Criação de pacote com o layout de empacotamento

Com a introdução dos pacotes de ativos, os desenvolvedores agora têm as ferramentas para criar mais pacotes, além de mais tipos de pacotes. À medida que um aplicativo fica maior e mais complexo, ele geralmente será composto por mais pacotes, e a dificuldade de gerenciar esses pacotes aumentará (especialmente se você estiver criando fora do Visual Studio e usando arquivos de mapeamento). Para simplificar o gerenciamento da estrutura de empacotamento de um aplicativo, você pode usar o layout de empacotamento suportado pelo MakeAppx.exe.

O layout de empacotamento é um único documento XML que descreve a estrutura de empacotamento do aplicativo. Ele especifica os agrupamentos de um aplicativo (principal e opcionais), os pacotes nos agrupamentos e os arquivos nos pacotes. Os arquivos podem ser selecionados de diferentes pastas, unidades e locais de rede. Curingas podem ser usados para selecionar ou excluir arquivos.

Depois que o layout de empacotamento de um aplicativo tiver sido configurado, ele será usado com o MakeAppx.exe para criar todos os pacotes de um aplicativo em uma única chamada de linha de comando. O layout de empacotamento pode ser editado para alterar a estrutura do pacote para atender às suas necessidades de implantação.

Exemplo de layout de embalagem simples

Veja um exemplo da aparência de um layout de embalagem simples:

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

Vamos detalhar esse exemplo para entender como ele funciona.

PacoteFamília

Esse layout de empacotamento criará um único arquivo de pacote de aplicativo simples com um pacote de arquitetura x64 e um pacote de ativos "Mídia".

O elemento PackageFamily é usado para definir um pacote de aplicativos. Você deve usar o atributo ManifestPath para fornecer um AppxManifest para o pacote, o AppxManifest deve corresponder ao AppxManifest para o pacote de arquitetura do pacote. O atributo ID também deve ser fornecido. Isso é usado com MakeAppx.exe durante a criação do pacote para que você possa criar apenas este pacote, se desejar, e este será o nome do arquivo do pacote resultante. O atributo FlatBundle é usado para descrever o tipo de pacote que você deseja criar, true para um flat bundle (que você pode ler mais sobre aqui) e false para um pacote clássico. O atributo ResourceManager é usado para especificar se os pacotes de recursos dentro desse pacote usarão MRT para acessar os arquivos. Isso é true por padrão, mas a partir do Windows 10, versão 1803, isso ainda não está pronto, portanto, esse atributo deve ser definido como false.

Pacote e AssetPackage

Dentro do PackageFamily, os pacotes que o pacote de aplicativos contém ou referências são definidos. Aqui, o pacote de arquitetura (também chamado de pacote principal) é definido com o elemento Package e o pacote de ativos é definido com o elemento AssetPackage. O pacote de arquitetura deve especificar para qual arquitetura o pacote serve, "x64", "x86", "arm" ou "neutral". Você também pode (opcionalmente) fornecer diretamente um AppxManifest especificamente para este pacote usando o atributo ManifestPath novamente. Se um AppxManifest não for fornecido, um será gerado automaticamente a partir do AppxManifest fornecido para o PackageFamily.

Por padrão, e AppxManifest será gerado para cada pacote dentro do pacote. Para o pacote de ativos, você também pode definir o atributo AllowExecution . Definir isso como false (o padrão) ajudará a diminuir o tempo de publicação do seu aplicativo, já que os pacotes que não precisam ser executados não terão a verificação de vírus bloqueando o processo de publicação (você pode saber mais sobre isso em Introdução aos pacotes de ativos).

Arquivos

Dentro de cada definição de pacote, você pode usar o elemento File para selecionar arquivos a serem incluídos neste pacote. O atributo SourcePath é onde os arquivos estão localmente. Você pode selecionar arquivos de diferentes pastas (fornecendo caminhos relativos), unidades diferentes (fornecendo caminhos absolutos) ou até mesmo compartilhamentos de rede (fornecendo algo como \\myshare\myapp\*). O DestinationPath é onde os arquivos irão parar dentro do pacote, em relação à raiz do pacote. ExcludePath pode ser usado (em vez dos outros dois atributos) para selecionar arquivos a serem excluídos daqueles selecionados por atributos SourcePath de outros elementos File dentro do mesmo pacote.

Cada elemento File pode ser usado para selecionar vários arquivos usando curingas. Em geral, o curinga único (*) pode ser usado em qualquer lugar dentro do caminho várias vezes. No entanto, um único curinga corresponderá apenas aos arquivos dentro de uma pasta e não a quaisquer subpastas. Por exemplo, pode ser usado no SourcePath para selecionar os arquivos C:\MyGame\Audios\UI.mp3 e C:\MyGame\Videos\intro.mp4, C:\MyGame\*\* mas não pode selecionar C:\MyGame\Audios\Level1\warp.mp3. O curinga duplo () também pode ser usado no lugar de nomes de pastas ou arquivos para corresponder a qualquer coisa recursivamente (**mas não pode ser ao lado de nomes parciais). Por exemplo, C:\MyGame\**\Level1\** pode selecionar C:\MyGame\Audios\Level1\warp.mp3 e C:\MyGame\Videos\Bonus\Level1\DLC1\intro.mp4. Os curingas também podem ser usados para alterar diretamente os nomes de arquivos como parte do processo de empacotamento se os curingas forem usados em locais diferentes entre a origem e o destino. Por exemplo, ter C:\MyGame\Audios\* para SourcePath e para DestinationPath pode selecionar C:\MyGame\Audios\UI.mp3 e Sound\copy_* fazer com que ele apareça no pacote como Sound\copy_UI.mp3. Em geral, o número de curingas simples e curingas duplos deve ser o mesmo para SourcePath e DestinationPath de um único elemento File.

Exemplo de layout de empacotamento avançado

Aqui está um exemplo de um layout de embalagem mais complicado:

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

Este exemplo difere do exemplo simples com a adição dos elementos ResourcePackage e Optional .

Os pacotes de recursos podem ser especificados com o elemento ResourcePackage . Dentro do ResourcePackage, o elemento Resources deve ser usado para especificar os qualificadores de recurso do pacote de recursos. Os qualificadores de recursos são os recursos que são suportados pelo pacote de recursos, aqui, podemos ver que há dois pacotes de recursos definidos e cada um deles contém os arquivos específicos em inglês e francês. Um pacote de recursos pode ter mais de um qualificador, isso pode ser feito adicionando outro elemento Resource dentro de Recursos. Um recurso padrão para a dimensão de recurso também deve ser especificado se a dimensão existir (dimensões sendo idioma, escala, dxfl). Aqui, podemos ver que o inglês é o idioma padrão, o que significa que, para os usuários que não têm um idioma de sistema de francês definido, eles voltarão a baixar o pacote de recursos em inglês e exibirão em inglês.

Cada pacote opcional tem seus próprios nomes de família de pacotes distintos e deve ser definido com elementos PackageFamily , enquanto especifica o atributo Optional para ser true. O atributo RelatedSet é usado para especificar se o pacote opcional está dentro do conjunto relacionado (por padrão, isso é verdadeiro) – se o pacote opcional deve ser atualizado com o pacote primário.

O elemento PrebuiltPackage é usado para adicionar pacotes que não estão definidos no layout de empacotamento a ser incluído ou referenciado no(s) arquivo(s) de pacote de aplicativos a serem criados. Nesse caso, outro pacote opcional de DLC está sendo incluído aqui para que o arquivo de pacote de aplicativo primário possa fazer referência a ele e fazer com que ele faça parte do conjunto relacionado.

Crie pacotes de aplicativos com um layout de empacotamento e MakeAppx.exe

Depois de ter o layout de empacotamento para seu aplicativo, você pode começar a usar o MakeAppx.exe para criar os pacotes do seu aplicativo. Para compilar todos os pacotes definidos no layout de empacotamento, use o comando:

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

Mas, se você estiver atualizando seu aplicativo e alguns pacotes não contiverem arquivos alterados, poderá compilar apenas os pacotes que foram alterados. Usando o exemplo de layout de empacotamento simples nesta página e criando o pacote de arquitetura x64, este é o nosso comando:

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

O /id sinalizador pode ser usado para selecionar os pacotes a serem criados a partir do layout de empacotamento, correspondendo ao atributo ID no layout. O /ip é usado para indicar onde a versão anterior dos pacotes está neste caso. A versão anterior deve ser fornecida porque o arquivo do pacote de aplicativos ainda precisa fazer referência à versão anterior do pacote de mídia . O /iv sinalizador é usado para incrementar automaticamente a versão dos pacotes que estão sendo criados (em vez de alterar a versão no AppxManifest). Como alternativa, os switches /pv e podem ser usados para fornecer diretamente uma versão do pacote (para todos os pacotes a serem criados) e /bv uma versão do pacote (para todos os pacotes a serem criados), respectivamente. Usando o exemplo de layout de empacotamento avançado nesta página, se você quiser criar apenas o pacote opcional Themes e o pacote do aplicativo Themes.main que ele faz referência, use este comando:

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

A /bc bandeira é usada para indicar que os filhos do pacote Temas também devem ser construídos (neste caso , Themes.main será construído). O /nbp sinalizador é usado para indicar que o pai do pacote Themes não deve ser criado. O pai do Themes, que é um pacote de aplicativos opcional, é o pacote de aplicativos principal: MyGame. Normalmente, para um pacote opcional em um conjunto relacionado, o pacote de aplicativo primário também deve ser criado para que o pacote opcional seja instalável, já que o pacote opcional também é referenciado no pacote de aplicativo primário quando está em um conjunto relacionado (para garantir o controle de versão entre os pacotes primário e opcional). A relação pai-filho entre pacotes é ilustrada no diagrama a seguir:

Packaging Layout Diagram