Partilhar via


Guia de implementação do Windows App SDK para aplicações dependentes do framework, empacotadas com localização externa ou não empacotadas

Este tópico fornece orientações sobre a implementação de aplicações que vêm embaladas com localização externa, ou que são não empacotadas, e que utilizam o Windows App SDK.

  • Essas aplicações são aplicações de ambiente de trabalho (não aplicações UWP).
  • Podem ser escritos numa linguagem .NET como C#, ou em C++.
  • Para a sua interface de utilizador, podem usar WinUI 3, ou WPF, ou WinForms, ou outro framework de interface.

Visão geral

Os desenvolvedores de aplicações empacotadas com localização externa e não empacotadas são responsáveis por implementar os pacotes de runtime do SDK de Aplicações Windows necessários para os seus utilizadores finais. Isto pode ser feito executando o instalador ou instalando diretamente os pacotes MSIX. Estas opções são descritas com mais detalhe na secção Deploy Windows App SDK runtime abaixo.

Aplicações empacotadas com localização externa e aplicações não empacotadas também têm requisitos adicionais de tempo de execução. Deve inicializar o acesso ao runtime do SDK da aplicação Windows usando a API Bootstrapper. Além disso, a API de Dependências Dinâmicas pode ser usada se a sua aplicação utilizar outros pacotes framework além do Windows App SDK. Estes requisitos são descritos com mais detalhe na secção Requisitos de Tempo de Execução para aplicações com localização externa ou não empacotadas abaixo.

Pré-requisitos

Pré-requisitos adicionais

  • As versões experimentais e de pré-visualização do Windows App SDK exigem que o sideloading esteja ativado para instalar o runtime.
    • O sideloading está ativado automaticamente no Windows 10 versão 2004 e posteriores.

    • Se o seu computador de desenvolvimento ou o computador de implementação estiver a correr o Windows 11, confirme se o sideloading está ativado:

      • Configurações>Privacidade e segurança>Para os programadores. Certifica-te de que a definição do modo Desenvolvedor está ativada.
    • Se o seu computador de desenvolvimento ou o computador de implementação estiver a correr Windows 10 versão 1909 ou uma versão anterior, confirme se o sideloading está ativado:

      • Configurações>Atualização & Segurança>Para programadores>Usa funcionalidades de programador. Confirme que Sideload apps ou modo de programador está selecionado.
    • A configuração do modo Desenvolvedor inclui funcionalidades como sideloading e outras mais.

      Observação

      Se o computador for gerido num ambiente empresarial, pode existir uma política que impeça a alteração dessas definições. Nesse caso, se aparecer um erro quando você ou a sua aplicação tentam instalar o runtime do SDK da aplicação Windows, contacte o seu profissional de TI para ativar o sideloading ou o modo Developer.

Implementar runtime do SDK de aplicações Windows

As aplicações empacotadas com localização externa e não empacotadas têm duas opções para distribuir o runtime do Windows App SDK:

  • Opção 1: Usar o Instalador: O instalador silencioso distribui todos os pacotes MSIX do Windows App SDK. Está disponível um instalador separado para cada uma das X64arquiteturas ,X86 e Arm64 .
  • Opção 2: Instalar os pacotes diretamente: Pode ter a sua configuração atual ou ferramenta MSI a transportar e instalar os pacotes MSIX para o Windows App SDK.

Opção 1: Usar o Instalador

Podes implementar todos os pacotes de runtime do Windows App SDK executando o instalador. O instalador está disponível em Downloads para o Windows App SDK. Ao executar o instalador (.exe), deverá ver uma saída semelhante à seguinte:

Deploying package: Microsoft.WindowsAppRuntime.1.0_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0

Deploying package: Microsoft.WindowsAppRuntime.1.0_0.318.928.0_x86__8wekyb3d8bbwe
Package deployment result : 0x0

Deploying package: MicrosoftCorporationII.WindowsAppRuntime.Main.1.0_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

Deploying package: Microsoft.WindowsAppRuntime.Singleton_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

Deploying package: Microsoft.WinAppRuntime.DDLM.0.318.928.0-x6_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

Deploying package: Microsoft.WinAppRuntime.DDLM.0.318.928.0-x8_0.318.928.0_x86__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

All install operations successful.

Podes executar o instalador sem interação do utilizador e suprimir toda a saída de texto com a --quiet opção:

WindowsAppRuntimeInstall.exe --quiet

Também pode optar por forçar a atualização dos pacotes MSIX e desligar quaisquer processos do Windows App SDK que estejam a correr usando essa --force opção. Esta funcionalidade foi introduzida na versão 1.1.

WindowsAppRuntimeInstall.exe --force

Para ver todas as opções de linha de comandos do instalador, execute WindowsAppRuntimeInstall --h.

Depois de concluída a instalação, pode executar a sua aplicação empacotada a partir de uma localização externa ou a aplicação não empacotada. Para um exemplo de como construir e executar uma aplicação empacotada com localização externa ou não empacotada que utiliza o Windows App SDK, veja Tutorial: Use a API bootstrapper numa aplicação empacotada com localização externa ou não empacotada que use o Windows App SDK.

Ligue o instalador do Windows App SDK à configuração da sua aplicação

Se tiveres um programa de configuração personalizado para a tua aplicação, podes encadear o processo de configuração do SDK do Windows App no processo de configuração da tua app. O instalador do SDK do Windows App atualmente não fornece uma interface predefinida, por isso terá de encadear usando a interface personalizada da sua instalação.

Pode iniciar e acompanhar silenciosamente a configuração do SDK da aplicação Windows enquanto mostra a sua própria visão do progresso da configuração usando o ShellExecute. O instalador do Windows App SDK desempacota silenciosamente o pacote Windows App MSIX e chama o método PackageManager.AddPackageAsync para completar a instalação. Isto é muito semelhante a outros instaladores em tempo de execução que possas ter usado, como .NET, Visual C++ ou DirectX.

Para um exemplo de código que demonstra como executar o instalador do Windows App SDK a partir do seu programa de configuração, veja a função RunInstaller nos testes funcionais do instalador.

Exemplo de instalador

Veja o exemplo abaixo para ver como iniciar o instalador a partir de um programa de configuração Win32 sem aparecer uma janela da consola durante a configuração:

Solução de problemas

Códigos de retorno

A tabela seguinte lista os códigos de retorno mais comuns para o instalador do SDK de Aplicações Windows .exe. Os códigos de retorno são os mesmos para todas as versões do instalador.

Código de retorno Description
0x0 A instalação ou provisionamento do pacote foi concluída com sucesso.
0x80073d06 Um ou mais pacotes falharam a instalação.
0x80070005 A instalação ou provisionamento em todo o sistema não foi possível porque a aplicação não está a ser executada com elevação, ou o utilizador que está a efetuar a instalação não tem privilégios de administrador.

Erros de instalação

Se o instalador do Windows App SDK devolver um erro durante a instalação, devolverá um código de erro que descreve o problema.

Opção 2: Implementar diretamente pacotes de runtime do Windows App SDK

Como alternativa a usar o instalador do Windows App SDK para implementação aos utilizadores finais, pode implementar manualmente os pacotes MSIX através do programa da sua aplicação ou do MSI. Esta opção pode ser ideal para programadores que querem mais controlo.

Para um exemplo que demonstre como o seu programa de configuração pode instalar os pacotes MSIX, veja install.cpp no código do instalador do Windows App SDK.

Para verificar se o Windows App SDK já está instalado (e, em caso afirmativo, que versão), pode verificar famílias específicas de pacotes ligando para PackageManager.FindPackagesForUserWithPackageTypes.

A partir de um processo desempacotado mediumIL (full trust) (ver elemento Aplicação), pode usar o seguinte código para verificar um pacote registado ao utilizador corrente:

using Windows.Management.Deployment;

public class WindowsAppSDKRuntime
{
    public static IsPackageRegisteredForCurrentUser(
        string packageFamilyName,
        PackageVersion minVersion,
        Windows.System.ProcessorArchitecture architecture,
        PackageTypes packageType)
    {
        ulong minPackageVersion = ToVersion(minVersion);

        foreach (var p : PackageManager.FindPackagesForUserWithPackageTypes(
            string.Empty, packageFamilyName, packageType)
        {
            // Is the package architecture compatible?
            if (p.Id.Architecture != architecture)
            {
                continue;
            }

            // Is the package version sufficient for our needs?
            ulong packageVersion = ToVersion(p.Id.Version);
            if (packageVersion < minPackageVersion)
            {
                continue;
            }

            // Success.
            return true;
        }

        // No qualifying package found.
        return false;
    }

    private static ulong ToVersion(PackageVersion packageVersion)
    {
        return ((ulong)packageVersion.Major << 48) |
               ((ulong)packageVersion.Minor << 32) |
               ((ulong)packageVersion.Build << 16) |
               ((ulong)packageVersion.Revision);
    }
}

No cenário acima, chamar FindPackagesForUserWithPackageTypes é preferível a chamar FindPackagesForUser. Isto porque podes restringir a pesquisa a (neste exemplo) apenas framework ou pacotes principais. E isso evita combinar outros tipos de pacotes (como resource, optional ou bundle) que não sejam do interesse deste exemplo.

Para usar o contexto de utilizador atual/chamante, defina o parâmetro userSecurityId como uma string vazia.

E agora algumas informações para te ajudar a decidir como chamar a função no exemplo do código acima. Um runtime devidamente instalado é composto por múltiplos pacotes que dependem da arquitetura da CPU do sistema:

  • Numa máquina x86: Fwk=[x86], Main=[x86], Singleton=[x86], DDLM=[x86].
  • Numa máquina x64: Fwk=[x86, x64], Main=[x64], Singleton=[x64], DDLM=[x86, x64].
  • Numa máquina arm64: Fwk=[x86, x64, arm64], Main=[arm64], Singleton=[arm64], DDLM=[x86, x64, arm64].

Para os pacotes Main e Singleton, a sua arquitetura deve corresponder à arquitetura do CPU do sistema; por exemplo, pacotes x64 em um sistema x64. No pacote Framework , um sistema x64 pode executar aplicações x64 e x86; De forma semelhante, um sistema ARM64 pode correr aplicações ARM64, X64 e X86. Uma verificação de pacote DDLM é semelhante a uma verificação de Framework, exceto que PackageType=main e o nome da família de pacotes difere, sendo que mais de um nome de família de pacotes diferente pode ser aplicável, devido ao esquema de nomenclatura único do DDLM. Para mais informações, consulte a especificação das embalagens MSIX . Portanto, as verificações são mais assim:

public static bool IsRuntimeRegisteredForCurrentUser(PackageVersion minVersion)
{
    ProcessorArchitecture systemArchitecture = DetectSystemArchitecture();

    return IsFrameworkRegistered(systemArchitecture, minVersion) &&
           IsMainRegistered(systemArchitecture, minVersion) &&
           IsSingletonRegistered(systemArchitecture, minVersion) &&
           IsDDLMRegistered(systemArchitecture, minVersion);
}

private static ProcecssorArchitecture DetectSystemArchitecture()
{
    // ...see the call to IsWow64Process2(), and how the result is used...
    // ...as per `IsPackageApplicable()` in
    // [install.cpp](https://github.com/microsoft/WindowsAppSDK/blob/main/installer/dev/install.cpp)
    // line 99-116...
    // ...WARNING: Use IsWow64Process2 to detect the system architecture....
    // ...         Other similar APIs exist, but don't give reliably accurate results...
}

private static bool IsFrameworkRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    // Check x86.
    if (!IsPackageRegisteredForCurrentUser(
        global::Microsoft.WindowsAppSDK.Runtime.Packages.Framework.PackageFamilyName,
        minVersion, ProcessorArchitecture.X86,
        PackageTypes.Framework))
    {
        return false;
    }

    // Check x64 (if necessary).
    if ((systemArchitecture == ProcessorArchitecture.X64) || 
        (systemArchitecture == ProcessorArchitcture.Arm64))
    {
        if (!IsPackageRegisteredForCurrentUser(
            global::Microsoft.WindowsAppSDK.Runtime.Packages.Framework.PackageFamilyName,
            minVersion, ProcessorArchitecture.X64,
            PackageTypes.Framework))
        {
            return false;
        }
    }

    // Check arm64 (if necessary).
    if (systemArchitecture == ProcessorArchitcture.Arm64)
    {
        if (!IsPackageRegisteredForCurrentUser(
            global::Microsoft.WindowsAppSDK.Runtime.Packages.Framework.PackageFamilyName,
            minVersion, ProcessorArchitecture.Arm64,
            PackageTypes.Framework))
        {
            return false;
        }
    }

    return true;
}

private static bool IsMainRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    return IsPackageRegisteredForCurrentUser(
        global::Microsoft.WindowsAppSDK.Runtime.Packages.Main.PackageFamilyName,
        minVersion,
        systemArchitecture,
        PackageTypes.Main);
}

private static bool IsSingletonRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    return IsPackageRegisteredForCurrentUser(
        global::Microsoft.WindowsAppSDK.Runtime.Packages.Singleton.PackageFamilyName,
        minVersion,
        systemArchitecture,
        PackageTypes.Main);
}

private static bool IsDDLMRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    // ...similar to IsFrameworkRegistered, but the packageFamilyName is more complicated...
    // ...and no predefined constant is currently available...
    // ...for more details, see
    // https://github.com/microsoft/WindowsAppSDK/blob/main/specs/Deployment/MSIXPackages.md.
}

A informação e o código acima cobrem o cenário básico de deteção. Para detetar se o tempo de execução está provisionado para todos os utilizadores, ou para fazer o acima a partir de um App Container, e/ou fazê-lo a partir de um processo empacotado mediumIL , é necessária lógica adicional.

Cenários de implementação

  • Instalação do Windows App SDK Runtime em todo o sistema: A instalação em todo o sistema altera a máquina para todos os utilizadores, incluindo novos que forem adicionados no futuro. Se a aplicação estiver a ser executada com privilégios elevados e o utilizador que faz a instalação tiver privilégios de administrador, então o instalador irá registar os pacotes MSIX ao nível do sistema, chamando o ProvisionPackageForAllUsersAsync. Se o registo em todo o sistema não for bem-sucedido, a instalação será realizada apenas pelo utilizador atual que está a fazer a instalação. Num ambiente empresarial gerido, o administrador de TI deve ser capaz de providenciar para todos normalmente.

  • Arquiteturas redistribuídas pelo instalador do Windows App SDK: O instalador do Windows App SDK está disponível nas x86arquiteturas , x64, e Arm64 . Cada versão do instalador inclui os pacotes MSIX apenas para a arquitetura específica que lhe dá nome. Por exemplo, se executares num x86WindowsAppRuntimeInstall.exe dispositivo x64 ou Arm64, então esse x86 instalador irá implementar nesse dispositivo apenas os pacotes para a arquitetura x86.

  • Todos os pacotes MSIX do Windows App SDK já estão instalados no computador: os pacotes MSIX são instalados numa localização de todo o sistema, com apenas uma cópia no disco. Se uma aplicação tentar instalar o Windows App SDK quando todas as dependências dos pacotes MSIX já estão instaladas na máquina, então a instalação não é realizada.

  • Um ou mais dos pacotes MSIX do Windows App SDK não estão instalados no computador: Ao implementar o Windows App SDK, tente sempre instalar todos os pacotes MSIX (framework, principal, singleton, DDLM) para garantir que todas as dependências estão instaladas e evitar perturbações na experiência do utilizador final.

Requisitos de tempo de execução para aplicações empacotadas com localização externa ou não empacotadas

As aplicações que vêm embaladas com localização externa ou não embaladas têm requisitos extra de tempo de execução para usar o SDK do Windows App. Isto envolve referenciar e inicializar o pacote Windows App SDK Framework em tempo de execução. Além disso, a API de Dependências Dinâmicas pode ser usada para referenciar outros pacotes framework fora do Windows App SDK.

Utilizar o runtime do SDK da aplicação Windows

As aplicações empacotadas com localização externa e as aplicações não empacotadas devem chamar a API do Bootstrapper para usar o Windows App SDK em tempo de execução. Isto é obrigatório antes de a aplicação poder utilizar funcionalidades do Windows App SDK como WinUI, App Lifecycle, MRT Core e DWriteCore. Um componente bootstrapper permite que aplicações empacotadas com local externo e desempacotadas desempenhem estas tarefas importantes:

  • Localize e carregue o pacote de estrutura do SDK de aplicativos do Windows no gráfico de pacotes do aplicativo.
  • Inicialize o DDLM (Dynamic Dependency Lifetime Manager) para o framework do SDK de aplicações do Windows. O objetivo do DDLM é impedir a manutenção do pacote framework do Windows App SDK enquanto este está em uso por uma aplicação com localização externa ou não empacotada.

A forma mais simples de carregar o runtime do SDK da Windows App para aplicações não empacotadas e com localização externa é definindo a propriedade <WindowsPackageType>None</WindowsPackageType> no seu ficheiro de projeto (.csproj ou .vcxproj). Também pode chamar a API do bootstrapper diretamente no código de arranque da sua aplicação para ter mais controlo sobre a inicialização. Para mais detalhes, veja Usar o runtime do Windows App SDK para aplicações empacotadas com localização externa ou não empacotadas e Tutorial: Use a API bootstrapper numa aplicação empacotada com localização externa ou não empacotada que utilize o Windows App SDK.

O suporte a Dependências Dinâmicas permite que aplicações empacotadas com localização externa e não empacotadas mantenham o seu mecanismo de implementação existente, como MSI ou qualquer instalador, e possam aproveitar o Windows App SDK na sua aplicação. Dependências dinâmicas podem ser usadas por aplicações empacotadas, empacotadas com local externo e não empacotadas; pois destinam-se principalmente a aplicações com local externo e não empacotadas.

Há um DDLM para cada versão e arquitetura do pacote de framework do Windows App SDK. Isso significa que, em um(a) x64 computador, poderá ter uma versão x86 e uma versão x64 do DDLM para suportar aplicações de ambas as arquiteturas.

Referenciar outros pacotes de framework usando a API de Dependências Dinâmicas

Se quiser usar funcionalidades noutros pacotes framework fora do Windows App SDK (por exemplo, DirectX), com localização externa e aplicações não empacotadas, pode chamar a API de Dependências Dinâmicas. Para além do componente bootstrapper, o Windows App SDK também fornece um conjunto mais amplo de funções C/C++ e classes WinRT que implementam a API dinâmica de dependências. Esta API foi concebida para ser usada para referenciar dinamicamente qualquer pacote framework em tempo de execução.

Para mais informações, consulte Utilizar pacotes de framework MSIX dinamicamente a partir da sua aplicação de ambiente de trabalho e o exemplo de Dependências Dinâmicas

Implementar ficheiros .winmd para a máquina alvo

Juntamente com a sua aplicação, recomendamos que implemente ficheiros de Metadados (.winmd) do Windows. Os metadados podem ser usados por várias APIs e comportamentos em tempo de execução, e a sua ausência pode limitar ou quebrar funcionalidades. Por exemplo, os metadados podem ser usados para marshar objetos através dos limites dos apartamentos; e a necessidade de marshar pode ser uma função do desempenho da máquina. Como não há uma forma determinística de saber se precisas de metadados, deves implementar .winmds a menos que estejas extremamente preocupado com o tamanho.