Pacotes de estrutura MSIX e dependências dinâmicas

Este artigo apresenta conceitos importantes relacionados a pacotes de estrutura MSIX. As informações neste artigo fornece contexto útil para ajudar você a entender melhor o design e a finalidade do recurso de dependências dinâmicas no SDK do Aplicativo do Windows e no sistema operacional Windows 11. Esse recurso permite que seus aplicativos referenciem e usem pacotes de estrutura MSIX em tempo de execução.

Pacotes de estrutura e o grafo de pacote

O MSIX é um formato de pacote que fornece uma experiência moderna de empacotamento e implantação. Ele também fornece uma forma limpa e confiável de empacotar bibliotecas redistribuíveis, conteúdo e componentes por meio de pacotes de estrutura MSIX. Um pacote de estrutura MSIX permite que aplicativos empacotados acessem componentes por meio de uma só fonte compartilhada no dispositivo do usuário, em vez de agrupá-los no pacote do aplicativo. Os pacotes de estrutura comuns incluem o SDK do Aplicativo do Windows (incluindo WinUI3), WinUI2, VCLibs e DirectX Runtime.

Começando com o Windows 8 e continuando até o Windows 10 e Windows 11, cada processo tem um grafo de pacote que fornece a lista de todos os pacotes disponíveis para o aplicativo, incluindo pacotes de estrutura, de recurso, opcionais e principais. Esse grafo permite que o aplicativo carregue DLLs, conteúdo e declarações de classe em tempo de execução fornecidos por um pacote referenciado. Historicamente, esse grafo foi corrigido no momento da criação do processo e não havia como alterá-lo em tempo de execução:

  • Para aplicativos empacotados, o grafo era inicializado com base nas dependências de pacote declaradas no elemento PackageDependency no manifesto do pacote do aplicativo. Ao criar um aplicativo empacotado, isso normalmente era feito para você durante o processo de build com base nas referências e dependências do projeto.
  • Para aplicativos não empacotados, o grafo do pacote estava vazio e não podia ser alterado. Portanto, os aplicativos não empacotados eram limitados à ordem de pesquisa de DLL padrão e não podiam acessar pacotes de estrutura.

Essa restrição de grafo de pacote estático é retirada com a introdução do suporte a dependências dinâmicas no SDK do aplicativo Windows e no Windows 11. Os desenvolvedores podem usar dependências dinâmicas para referenciar e usar pacotes de estrutura MSIX dos próprios aplicativos em tempo de execução. As dependências dinâmicas removem a restrição de grafo de pacote estático de aplicativos, e os desenvolvedores podem decidir como querem aproveitar os pacotes de estrutura.

Principais cenários para dependências dinâmicas

Embora as dependências dinâmicas permitam a qualquer aplicativo adicionar uma dependência de estrutura de pacote em tempo de execução, esse recurso destina-se a ser usado principalmente por aplicativos empacotados com localização externa ou aplicativos não empacotados. Os aplicativos empacotados ainda podem continuar adicionando dependências estáticas por meio do elemento PackageDependency no manifesto do pacote.

Modelo de manutenção para pacotes de estrutura

O recurso de dependências dinâmicas preserva a integridade do pipeline de manutenção para o pacote de estrutura que está sendo referenciado e usado dinamicamente em tempo de execução.

Os pacotes de estrutura MSIX dão suporte para manutenção em um modelo lado a lado, o que significa que cada versão é instalada em uma pasta própria separada com versão. Isso permite que os aplicativos em uso sejam capazes de permanecer em funcionamento mesmo quando um aplicativo mais recente instala uma versão mais recente do pacote de estrutura. O sistema operacional tem lógica de desinstalação para quando excluir versões mais antigas de um determinado pacote de estrutura, com base na presença de referências em tempo de instalação e referências em tempo de execução para o pacote.

  • Quando um aplicativo é instalado, ele pode criar uma referência em tempo de instalação para um pacote de estrutura. Essa referência informa ao sistema operacional que o aplicativo tem uma dependência do pacote de estrutura especificado para que o sistema operacional não desinstale o pacote de estrutura enquanto o aplicativo estiver instalado.
  • Quando um aplicativo precisa usar APIs ou conteúdo em um pacote de estrutura, ele pode adicionar uma referência em tempo de execução ao pacote de estrutura. Essa referência informa ao sistema operacional que o pacote de estrutura está em uso ativo e para lidar com as atualizações de versão de maneira lado a lado. Se uma nova versão do pacote de estrutura estiver instalada, mas um aplicativo em execução tiver uma versão mais antiga em uso, o sistema operacional não poderá remover a versão mais antiga até que todas as referências em tempo de execução à versão mais antiga sejam removidas.

Por exemplo, neste cenário:

  • O aplicativo A está em execução e usando a versão 1.0.0.0 de um determinado pacote de estrutura.
  • O aplicativo B está instalado e tem uma dependência da versão 1.0.0.1 do mesmo pacote de estrutura.

Nesse cenário, ambas as versões do pacote de estrutura serão instaladas e ficarão em uso pelo Aplicativo A e pelo Aplicativo B. No entanto, quando o Aplicativo A for fechado pelo usuário e reiniciado, ele optará pela versão mais recente (1.0.0.1) do pacote de estrutura. Neste ponto, o requisito de referência em tempo de execução não é mais válido para a versão 1.0.0.0 do pacote de estrutura, e o sistema operacional pode remover com segurança a versão 1.0.0.0. Posteriormente, quando o Aplicativo A e o Aplicativo B forem desinstalados pelo usuário, o requisito de referência em tempo de instalação não será mais válido e será seguro para o sistema operacional remover totalmente o pacote de estrutura.

Para aplicativos empacotados que usam o elemento PackageDependency para especificar referências estáticas a pacotes de estrutura, as referências em tempo de instalação para pacotes de estrutura são rastreadas pelo sistema operacional quando o aplicativo é instalado ou desinstalado. Para referências em tempo de execução que são gerenciadas usando o recurso de dependências dinâmicas, o sistema operacional sabe quando um aplicativo empacotado está em execução e evitará remover os próprios pacotes de estrutura em uso quando um mais recente estiver disponível.