Compartilhar via


Criação do pacote com o layout de empacotamento

Com a introdução de pacotes de ativos, os desenvolvedores agora têm as ferramentas para criar mais pacotes além de mais tipos de pacote. À 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 compatível com MakeAppx.exe.

O layout de empacotamento é um único documento XML que descreve a estrutura de empacotamento do aplicativo. Ele especifica os pacotes de um aplicativo (primário e opcional), os pacotes nos pacotes e os arquivos nos pacotes. Os arquivos podem ser selecionados em 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 for configurado, ele será usado com MakeAppx.exe para criar todos os pacotes para 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 simples de embalagem

Aqui está um exemplo de como é um layout de empacotamento 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 dividir este exemplo para entender como ele funciona.

PackageFamily

Esse layout de empacotamento criará um único arquivo simples de pacote de aplicativo com um pacote de arquitetura x64 e um pacote de ativos intitulado "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 esse pacote, se desejar, e esse será o nome do arquivo do pacote resultante. O atributo FlatBundle é usado para descrever que tipo de pacote você deseja criar, true para um pacote simples (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 o MRT para acessar os arquivos. Isso é verdadeiro 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

No PackageFamily, os pacotes que o pacote do aplicativo contém ou as 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 esse 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, 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 aplicativo, pois os pacotes que não precisam ser executados não terão a verificação de vírus bloquear o processo de publicação (você pode saber mais sobre isso na 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 pastas diferentes (fornecendo caminhos relativos), unidades diferentes (fornecendo caminhos absolutos) ou até mesmo compartilhamentos de rede (fornecendo algo parecido \\myshare\myapp\*). O DestinationPath é onde os arquivos acabarão 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 dos selecionados pelos atributos SourcePath de outros elementos de arquivo no mesmo pacote.

Cada elemento File pode ser usado para selecionar vários arquivos usando curingas. De modo geral, um único caractere curinga (*) pode ser usado em qualquer lugar dentro do caminho qualquer número de vezes. No entanto, um único caractere curinga corresponderá apenas aos arquivos dentro de uma pasta e não de nenhuma subpasta. Por exemplo, C:\MyGame\*\* pode ser usado no SourcePath para selecionar os arquivos C:\MyGame\Audios\UI.mp3 e C:\MyGame\Videos\intro.mp4, mas não pode selecionar C:\MyGame\Audios\Level1\warp.mp3. O curinga duplo (**) também pode ser usado no lugar de nomes de pasta ou arquivo 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 caracteres curinga também podem ser usados para alterar os nomes de arquivos diretamente como parte do processo de empacotamento, se esses caracteres curingas forem usados em locais diferentes na origem e no destino. Por exemplo, ter C:\MyGame\Audios\* para SourcePath e Sound\copy_* para DestinationPath pode selecionar C:\MyGame\Audios\UI.mp3 e fazer com que ele apareça no pacote como Sound\copy_UI.mp3. De modo geral, o número de caracteres curinga simples e duplos deve ser o mesmo para o SourcePath e o DestinationPath de um único elemento de Arquivo.

Exemplo de layout de empacotamento avançado

Aqui está um exemplo de um layout de empacotamento 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 de ResourcePackage e Optional.

Os pacotes de recursos podem ser especificados com o elemento ResourcePackage . No ResourcePackage, o elemento Resources deve ser usado para especificar os qualificadores de recursos do pacote de recursos. Os qualificadores de recursos são os recursos compatíveis com o 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 em Recursos. Um recurso padrão para a dimensão de recurso também deve ser especificado se a dimensão existir (dimensões sendo linguagem, escala, dxfl). Aqui, podemos ver que o inglês é o idioma padrão, o que significa que, para usuários que não têm o idioma do sistema configurado para francês, eles recorrerão ao download do pacote de recursos em inglês e à exibição em inglês.

Os pacotes opcionais têm seus próprios nomes de família de pacotes distintos e devem ser definidos com elementos PackageFamily , especificando o atributo Opcional como verdadeiro. 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 são definidos no layout de empacotamento a serem incluídos ou referenciados nos arquivos do pacote do aplicativo a serem criados. Nesse caso, outro pacote opcional de DLC está sendo incluído aqui para que o arquivo de pacote do aplicativo primário possa referenciá-lo e fazer com que ele faça parte do conjunto relacionado.

Compilar pacotes de aplicativos com o layout e o MakeAppx.exe do empacotamento

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

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

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

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, correspondente ao atributo ID no layout. O /ip é usado para indicar onde a versão anterior dos pacotes está nesse caso. A versão anterior deve ser fornecida porque o arquivo de pacote do aplicativo ainda precisa referenciar a versão anterior do pacote de mídia . O /iv flag é 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 comutadores /pv e /bv podem ser usados para fornecer diretamente uma versão do pacote (para que todos os pacotes sejam criados) e uma versão do conjunto (para que todos os conjuntos sejam criados), respectivamente. Usando o exemplo de layout de empacotamento avançado nesta página, se você quiser criar apenas o pacote opcional Temas e o pacote de aplicativo Themes.main que ele faz referência, você usará este comando:

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

O /bc flag é usado para indicar que os filhos do pacote Temas também devem ser criados (nesse caso, Themes.main será criado). O sinalizador /nbp é usado para indicar que o pai do pacote Temas não deve ser compilado. O pai de Temas, que é um pacote de aplicativo opcional, é o pacote de aplicativo 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, pois o pacote opcional também é referenciado no pacote do aplicativo primário quando ele está em um conjunto relacionado (para garantir o controle de versão entre os pacotes primários e opcionais). A relação pai filho entre pacotes é ilustrada no diagrama a seguir:

Diagrama de Layout de Empacotamento