Usar a linha de comando winapp com .NET

Este guia deve funcionar para a maioria dos tipos de projetos .NET. Os passos foram testados tanto com projetos de consola como de interface como o WPF. Para exemplos práticos, consulta os exemplos dotnet-app (consola) e wpf-app (WPF) na pasta de exemplos.

Este guia demonstra como utilizar a CLI winapp com uma aplicação .NET para depurar com identidade de pacote e empacotar a sua aplicação no formato MSIX.

A identidade de pacote é um conceito central no modelo de Windows app. Permite que a sua aplicação aceda a APIs específicas do Windows (como Notificações, Segurança, APIs de IA, etc.), tenha uma experiência limpa de instalação/desinstalação e muito mais.

Um executável padrão (como um criado com dotnet build) não tem identidade de pacote. Este guia mostra como adicioná-lo para depuração e depois empacotar para distribuição.

Pré-requisitos

  1. .NET SDK: Instalar o .NET SDK (requer um reinício após a instalação):

    winget install Microsoft.DotNet.SDK.10 --source winget
    
  2. winapp CLI: Instale a winapp ferramenta via winget (ou atualize se já estiver instalado):

    winget install Microsoft.winappcli --source winget
    

1. Criar uma nova aplicação .NET

Comece por criar uma aplicação simples de consola .NET:

dotnet new console -n dotnet-app
cd dotnet-app

Executa para garantir que tudo está a funcionar:

dotnet run

A saída deve ser "Olá, Mundo!"

2. Atualizar o código para verificar a identidade

Vamos atualizar a aplicação para verificar se está a correr com identidade de pacote. Vamos usar a API do Windows Runtime para aceder às APIs dos Pacotes.

Primeiro, atualize o ficheiro do seu projeto para apontar uma versão específica do SDK do Windows. Abra dotnet-app.csproj e altere TargetFramework para incluir a versão do SDK do Windows:

  <TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>

Isto dá-lhe acesso às APIs do Windows Runtime sem necessidade de pacotes adicionais.

Agora substitui o conteúdo de Program.cs pelo seguinte código. Este código tenta recuperar a identidade atual do pacote usando a API do Windows Runtime. Se tiver sucesso, imprime o Nome da Família do Pacote; caso contrário, imprime "Não embalado".

using Windows.ApplicationModel;

try
{
    var package = Package.Current;
    var familyName = package.Id.FamilyName;
    Console.WriteLine($"Package Family Name: {familyName}");
}
catch (InvalidOperationException)
{
    // Thrown when app doesn't have package identity
    Console.WriteLine("Not packaged");
}

3. Correr sem identidade

Agora, executa a aplicação como de costume:

dotnet run

Deves ver a saída "Não empacotada". Isto confirma que o executável padrão está a correr sem qualquer identidade de pacote.

4. Inicializar o Project com o winapp CLI

O winapp init comando deteta .csproj automaticamente ficheiros e executa uma configuração específica para .NET. Configura tudo o que precisas de uma só vez: valida o teu TargetFramework, adiciona os pacotes NuGet necessários, gera o manifesto da aplicação e os assets.

Execute o seguinte comando e siga as indicações:

winapp init

Quando solicitado:

  • Nome do pacote: Pressione Enter para aceitar o predefinido (dotnet-app)
  • Nome do Publicador: Pressione Enter para aceitar o padrão ou inserir o seu nome
  • Versão: Pressione Enter para aceitar 1.0.0.0
  • Descrição: Pressione Enter para aceitar o padrão (Aplicação Windows) ou introduza uma descrição
  • Configuração do SDK de Aplicações Windows: Selecione Estável, Pré-visualização ou Experimental (determina qual versão do SDK de Aplicações Windows é adicionada)
  • Atualização de TargetFramework: Se TargetFramework não incluir uma versão suportada do SDK do Windows, ser-lhe-á solicitado que a atualize (por exemplo, para net10.0-windows10.0.26100.0)
  • Modo Desenvolvedor: Se lhe perguntarem sobre o "Modo Desenvolvedor", pode ativá-lo se quiser, mas esteja ciente de que requer privilégios administrativos

Este comando irá fazer:

  • Atualize o TargetFramework no seu .csproj para um TFM do Windows suportado (se necessário)
  • Adicione Microsoft.WindowsAppSDK, Microsoft.Windows.SDK.BuildTools, e Microsoft.Windows.SDK.BuildTools.WinApp referências de pacotes NuGet ao seu .csproj
  • Crie Package.appxmanifest uma Assets pasta para a identidade da sua aplicação

Observação

Ao contrário dos projetos nativos/C++, o fluxo do .NET não cria um ficheiro winapp.yaml. Os pacotes NuGet são geridos diretamente pelo seu .csproj. Após a clonagem, execute winapp restore ou dotnet restore.

Pode abrir Package.appxmanifest para personalizar ainda mais propriedades como o nome de visualização, publicador e capacidades.

Para verificar se os pacotes foram adicionados ao seu projeto:

dotnet list package

Deves ver Microsoft.WindowsAppSDK e Microsoft.Windows.SDK.BuildTools aparecer na saída.

Saída da consola (nada a fazer)

Como estamos a construir uma aplicação para consola, a saída da consola tem de permanecer no terminal atual. A ativação por AUMID faz com que uma aplicação empacotada não tenha consola, pelo que uma aplicação de consola seria executada corretamente e não imprimiria nada.

A WinApp trata disto por si: uma aplicação com OutputType=Exe é lançada através de um alias de execução, que herda o stdin/stdout/stderr do seu terminal. Adiciona o uap5:ExecutionAlias necessário ao manifesto que prepara, pelo que não há nada a configurar.

As aplicações UI (WPF, WinForms, WinUI) renderizam a sua própria janela, por isso mantêm a ativação do AUMID.

Para forçar ainda assim o AUMID numa aplicação de consola, defina o seguinte dentro de qualquer <PropertyGroup> em dotnet-app.csproj — a aplicação é então executada sem uma consola e não imprime nada no terminal:

<WinAppRunUseExecutionAlias>false</WinAppRunUseExecutionAlias>

Se preferires escolher tu mesmo o nome do comando, executa winapp manifest add-alias para declarar um em Package.appxmanifest; qualquer alias que cries é usado tal como está.

5. Depuração com Identidade

Uma vez que winapp init adicionou o pacote NuGet Microsoft.Windows.SDK.BuildTools.WinApp ao seu projeto, pode simplesmente executar:

dotnet run

Isto invoca automaticamente winapp run nos bastidores — criando um pacote de esquema não compactado, registando-o no Windows e iniciando a sua aplicação com identidade de pacote completa.

Os argumentos que escreves depois dotnet run vão para a tua candidatura, exatamente como fariam se o projeto não referenciasse este pacote:

dotnet run --devtools          # your app receives --devtools
dotnet run -- --devtools       # identical: the SDK consumes the -- before forwarding

Utilize -- quando a flag da sua aplicação também é uma opção dotnet run (--configuration, --framework, --project, -c, -f, -r, ...) — sem isso, o SDK fica com o token e a sua aplicação nunca o recebe:

dotnet run -- --configuration Release   # your app receives --configuration Release

Configure o próprio iniciador do WinApp através das propriedades WinAppRun* do MSBuild. O MSBuild consome estes, por isso nunca chegam à sua aplicação:

dotnet run -p:WinAppRunDebugOutput=true --devtools

Aqui, a propriedade configura o WinApp enquanto --devtools é passado para a sua aplicação. Consulte dotnet runo suporte para ver a lista completa de propriedades, incluindo as propriedades que não podem ser combinadas.

Observação

Pode ver avisos de vulnerabilidade do NuGet (NU1900) sobre as fontes dos pacotes. Estas são seguras para ignorar — não afetam a tua build.

Deverias ver resultados semelhantes a:

Package Family Name: dotnet-app_12345abcde

Isto confirma que a sua aplicação está a correr com uma identidade de pacote válida!

Alternativa: Manual winapp run

Se não usaste winapp init (ou removeste o pacote NuGet), podes compilar e correr manualmente. winapp run aceita o projeto diretamente (modo de projeto) — compila o .csproj e inicia-o, por isso não tens de indicar a pasta de saída da compilação nem de compilar separadamente:

# Build and run the project in one step (project mode)
winapp run .

# ...or run a specific project / configuration / architecture
winapp run .\dotnet-app.csproj -c Debug --arch x64

Para executar a configuração nativa AOT do projeto, ative o AOT no projeto e execute:

winapp run . --aot
winapp run . --aot -c Release

Usa x64 ou ARM64. Para uma substituição pontual, acrescente -p PublishAot=true.

Ainda podes apontar winapp run para uma pasta de saída pré-construída, se preferires (modo pasta):

dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0

O modo Project suporta aplicações WinUI tanto empacotadas como não embaladas — deteta quais do project WindowsPackageType e instala automaticamente o Aplicação do Windows Runtime com arquitetura correspondente. Para forçar uma execução não empacotada de um projeto empacotado, adicione -p WindowsPackageType=None.

As aplicações multi-projeto (uma aplicação que referenciam bibliotecas de classes) são construídas corretamente: a winapp mantém AnyCPU/netstandard2.0 referências na sua plataforma compatível em vez de forçar a arquitetura da aplicação ao longo do grafo. Apenas o RID mantém-se como padrão; quando a configuração efetiva requer um perfil autónomo (por exemplo, uma versão Release recortada), o winapp seleciona o perfil correspondente sem alterar as plataformas das bibliotecas referenciadas.

Os dotnet build fluxos de saída são transmitidos em direto, sendo a invocação exata apresentada primeiro. Adicione --verbose para os próprios registos de decisão de compilação da winapp. Requer o SDK .NET 8.0.100 ou mais recente. Veja winapp run na referência de utilização para a lista completa de opções.

Nenhum SDK do Windows instalado? Os projetos de autoria em C#/WinRT normalmente precisam de um SDK Windows registado para serem construídos. Quando o modo de projeto não deteta nenhum destes ambientes (CI limpo, containers, máquinas de desenvolvimento sem SDK), faz o cswinrt apontar para os winmds do pacote restaurado automaticamente Microsoft.Windows.SDK.NET.Ref, para que a compilação continue a ser bem-sucedida — não é necessária qualquer ação. Não faz nada quando um SDK é instalado ou quando se configura -p CsWinRTWindowsMetadata=… por si próprio.

Para adicionar novamente o pacote NuGet: dotnet add package Microsoft.Windows.SDK.BuildTools.WinApp --prerelease

Sugestão

Para desativar a integração automática dotnet run, adicione <EnableWinAppRunSupport>false</EnableWinAppRunSupport> ao seu .csproj. Consulta a documentação de suporte ao dotnet run para opções de personalização.

Alternativa: Identidade de pacote disperso

Se precisares de comportamento de pacotes esparso especificamente (identidade sem copiar ficheiros), podes usar create-debug-identity em vez disso. Isto regista um pacote esparso que aponta para o seu exe, em vez de criar um layout solto:

winapp create-debug-identity .\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe

Depois executa o executável diretamente (não o uses dotnet run porque pode reconstruir/sobrescrever o ficheiro):

.\bin\Debug\net10.0-windows10.0.26100.0\dotnet-app.exe

Alternativa: alvo manual MSBuild

Se preferires não usar o pacote NuGet, podes adicionar um alvo MSBuild personalizado que corre create-debug-identity depois das compilações de Debug. Adicione isto ao seu .csproj ficheiro no final, pouco antes da etiqueta de fecho </Project> :

  <!-- Automatically apply debug identity after Debug builds -->
  <Target Name="ApplyDebugIdentity" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
    <Exec Command="winapp create-debug-identity &quot;$(TargetDir)$(TargetName).exe&quot;" 
          WorkingDirectory="$(ProjectDir)" 
          IgnoreExitCode="false" />
  </Target>

Com esta configuração, dotnet build aplica a identidade de depuração e pode executar o executável diretamente. Note que dotnet run pode voltar a compilar e sobrescrever a identidade, por isso execute manualmente o ficheiro exe após a compilação.

Sugestão

Para fluxos de trabalho avançados de depuração (anexação de depuradores, configuração do IDE, depuração de arranque), consulte o Guia de Depuração.

Quando saltar isto: Se preferir controlo explícito sobre quando a identidade é aplicada, ou se estiver a trabalhar em código que não precisa de identidade durante a maior parte do seu ciclo de desenvolvimento, a abordagem manual acima pode ser mais simples.

6. Utilização do SDK de Aplicações Windows (Opcional)

O SDK de Aplicações Windows dá-lhe acesso a APIs modernas do Windows para além do que o SDK base do Windows fornece — coisas como o sistema de notificações, APIs de janelas, gestão do ciclo de vida da aplicação e IA no dispositivo. Se a sua aplicação precisar de alguma destas funcionalidades, este passo é para si. Se só precisares de identidade de pacote para distribuição, podes saltar para o passo 7.

Se executou winapp init (Passo 4), Microsoft.WindowsAppSDK já foi adicionado como referência a pacote NuGet ao ficheiro .csproj. Pode verificar com dotnet list package. Se ignoraste a configuração do SDK durante o init, ou precisares de o adicionar manualmente, executa:

dotnet add package Microsoft.WindowsAppSDK

Atualizar Program.cs

Substitua todo o conteúdo de Program.cs pelo código seguinte, que adiciona uma verificação da versão do Aplicação do Windows Runtime:

using Windows.ApplicationModel;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            var package = Package.Current;
            var familyName = package.Id.FamilyName;
            Console.WriteLine($"Package Family Name: {familyName}");
            
            // Get Windows App Runtime version using the API
            var runtimeVersion = Microsoft.Windows.ApplicationModel.WindowsAppRuntime.RuntimeInfo.AsString;
            Console.WriteLine($"Windows App Runtime Version: {runtimeVersion}");
        }
        catch (InvalidOperationException)
        {
            // Thrown when app doesn't have package identity
            Console.WriteLine("Not packaged");
        }
    }
}

Compilar e Executar

Reconstrua e execute a aplicação com o SDK de Aplicações Windows. Desde que adicionámos o WinAppSDK, precisamos de re-registar com identidade, por isso winapp adiciona a dependência de runtime. Se adicionou o pacote WinApp NuGet (recomendado), basta executar dotnet run. Caso contrário (substitua dotnet-app pelo nome do teu projeto):

dotnet build -c Debug
winapp run .\bin\Debug\net10.0-windows10.0.26100.0

Agora deverá ver resultados como:

Package Family Name: dotnet-app.debug_12345abcde
Windows App Runtime Version: 8000.770.947.0

O pacote NuGet do SDK de Aplicações Windows inclui todos os assemblies necessários para aceder a APIs Windows modernas, incluindo:

  • Notificações e blocos dinâmicos
  • Gestão de janelas e ciclo de vida da aplicação
  • Notificações push
  • E muitos mais componentes do SDK de Aplicações Windows

Para uso mais avançado de SDK de Aplicações Windows, consulte a documentação SDK de Aplicações Windows.

7. Pacote com MSIX

Quando estiver pronto para distribuir a sua aplicação, pode empacotá-la como MSIX usando o mesmo manifesto.

Compilação para lançamento

Primeiro, construa a sua aplicação em modo de lançamento para um desempenho ótimo:

dotnet build -c Release

Observação

Pode ver avisos de vulnerabilidade do NuGet (NU1900). Podem ser ignoradas em segurança e não afetam o output da build.

Gerar um Certificado de Desenvolvimento

Antes de empacotar, precisa de um certificado de desenvolvimento para assinar. Gera uma, caso ainda não o tenha feito:

winapp cert generate --if-exists skip

Assinar e Embalar

Agora podes embalar e assinar. Indica ao comando pack a pasta de saída da compilação (substitui dotnet-app e o caminho do TFM pelos valores do seu projeto):

# package and sign the app with the generated certificate
winapp pack .\bin\Release\net10.0-windows10.0.26100.0 --manifest .\Package.appxmanifest --cert .\devcert.pfx 

Nota: O pack comando usa automaticamente o Package.appxmanifest do seu diretório atual e copia-o para a pasta de destino antes de o empacotar. O ficheiro .msix gerado estará no diretório atual.

Dica: Também pode ignorar a localização da pasta de saída da compilação e criar o pacote diretamente a partir do projeto — winapp package .\dotnet-app.csproj --cert .\devcert.pfx publica o projeto e cria um pacote com o resultado gerado numa única etapa (no modo de projeto, a configuração predefinida é Release). O modo de projeto aceita as opções de construção -c, --arch, -f, --no-build, --no-restore, -p; adicione --no-build para empacotar uma compilação existente sem recompilar.

Instalar o Certificado

Antes de poderes instalar o pacote MSIX, precisas de instalar o certificado de desenvolvimento. Executa este comando como administrador:

winapp cert install .\devcert.pfx

Instalar e Executar

Instale o pacote clicando duas vezes no ficheiro *.msix gerado.

Agora pode executar a sua aplicação a partir de qualquer ponto do terminal escrevendo:

dotnet-app

Deves ver o resultado "Nome da Família do Pacote", confirmando que está instalado e a funcionar com a identidade.

Sugestão

Se precisares de reempacotar a tua aplicação (por exemplo, depois de alterações de código), incrementa o Version no teu Package.appxmanifest antes de correr winapp pack novamente. O Windows requer um número de versão superior para atualizar um pacote instalado.

Tips

  1. Quando estiver pronto para a distribuição, pode assinar o seu MSIX com um certificado de assinatura de código de uma Autoridade Certificadora, para que os seus utilizadores não tenham de instalar um certificado auto-assinado.
  2. A Microsoft Store assina o MSIX por si, não precisa de assinar antes de submeter.
  3. Pode ser necessário criar vários pacotes MSIX, um para cada arquitetura que suporta (x64, Arm64). Use a opção -r com dotnet build para direcionar arquiteturas específicas: dotnet build -c Release -r win-x64 ou dotnet build -c Release -r win-arm64.

Automatização da Embalagem MSIX (Opcional)

Para automatizar o empacotamento do MSIX como parte das suas versões de Release, adicione este alvo ao seu .csproj ficheiro (pode adicioná-lo juntamente com o alvo de identidade de depuração):

  <!-- Automatically package as MSIX after Release builds -->
  <Target Name="PackageMsix" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
    <!-- Package and sign directly from build output -->
    <Exec Command="winapp pack &quot;$(TargetDir.TrimEnd('\'))&quot; --cert &quot;$(ProjectDir)devcert.pfx&quot;" 
          WorkingDirectory="$(ProjectDir)" 
          IgnoreExitCode="false" />
  </Target>

Com esta configuração:

  • Construir no modo Release (dotnet build -c Release) criará automaticamente o pacote MSIX
  • O MSIX é embalado e assinado com o seu certificado de desenvolvimento
  • O ficheiro final .msix estará na raiz do projeto

Também pode criar uma configuração personalizada (por exemplo, PackagedRelease) modificando a condição para '$(Configuration)' == 'PackagedRelease'.

Próximas Etapas

  • Distribua via winget: Submeta o seu MSIX ao Repositório Comunitário Windows Gestor de Pacotes
  • Publicar no Microsoft Store: Use winapp store para submeter o seu pacote
  • Configurar CI/CD: Use o GitHub Action para automatizar o empacotamento no seu pipeline
  • Explore Windows APIs: Com a identidade do pacote, pode agora usar Notifications, on-device AI e outras APIs dependentes da identidade