Depuração com Identidade de Pacote

Muitas APIs do Windows (notificações push, tarefas em segundo plano, alvo de partilha, tarefas de arranque, e APIs de IA do Windows) exigem que a sua app tenha package identity. Durante o desenvolvimento, não quer construir um instalador MSIX completo sempre que testa — o winapp fornece dois comandos para atribuir a identidade da sua aplicação em tempo real.

Usar Visual Studio com um projeto de embalagem? Se já estiver a utilizar o Visual Studio para o seu projeto empacotado, provavelmente não precisa do winapp para debug. O Visual Studio já trata do registro de pacotes, identidade, ativação de AUMID, anexação do depurador e depuração do código de ativação — tudo mediante o F5. Também oferece Depurar → Outros Alvos de Depuração → Depurar Pacote de Aplicação Instalado para cenários avançados. Os fluxos de trabalho abaixo são mais úteis para utilizadores de VS Code, fluxos de trabalho baseados em terminais e frameworks que o VS não empacota nativamente (Rust, Flutter, Tauri, Electron, C++ simples).

Duas abordagens: winapp run vs create-debug-identity

winapp run create-debug-identity
O que regista Pacote completo de layout livre (pasta inteira) Pacote esparso (único exe)
Como a aplicação é lançada Lançado pela winapp (alias de ativação ou execução AUMID) Tu próprio inicias o exe (linha de comandos, IDE, etc.)
Simula MSIX instalação Sim — mais próximo do comportamento de produção Não — apenas identidade dispersa
Os ficheiros mantêm-se no lugar Copiado para um diretório de layout do AppX Sim — o exe mantém-se no seu percurso original
Âmbito de identidade Conteúdo inteiro da pasta (exe, DLLs, assets) Executável único
Amigável para depuradores Anexe ao PID após o lançamento ou use --no-launch e depois lança através de um alias. Inicie diretamente a partir do depurador do seu IDE — o exe mantém a sua identidade independentemente
Suporte para aplicações de consola --with-alias Mantém o STDIN/STDOUT no terminal Executa o exe diretamente no terminal
Melhor para A maioria dos frameworks (.NET, C++, Rust, Flutter, Tauri) Electron, ou quando precisas de controlo total do depurador IDE (F5)

Quando usar qual

Predefinição: winapp run

Usar winapp run para a maioria dos fluxos de trabalho de desenvolvimento. Simula uma instalação real do MSIX — a tua aplicação recebe a mesma identidade, capacidades e associações de ficheiros que teria em produção.

# Build your app, then:
winapp run .\build\output

Utilize create-debug-identity quando:

  • O teu exe é separado da tua saída de build — por exemplo, aplicações Electron onde electron.exe se encontra em node_modules/
  • Precisas de depurar o código de arranque e não consegues anexar um depurador rápido o suficiente após o lançamento do AUMID
  • Com alguns depuradores onde não se pode iniciar com AUMID e é necessário ter identidade no processo lançado — create-debug-identity regista o exe, por isso tem identidade independentemente de como foi iniciado
  • Estás a testar especificamente o comportamento de pacotes esparsos (AllowExternalContent, TrustedLaunch)
# Register identity for an exe, then launch it however you want:
winapp create-debug-identity .\bin\Debug\myapp.exe
.\bin\Debug\myapp.exe   # or F5 in your IDE

Cenários de depuração

Cenário A: Apenas operar com identidade

O fluxo de trabalho mais simples — construir, executar com identidade, concluído.

winapp run .\build\Debug

O Winapp regista a pasta como um pacote de layout solto e lança a aplicação. As APIs que exigem identidade funcionam imediatamente. Isto cobre a maioria dos cenários de desenvolvimento e testes.

Para aplicações de consola que precisam de stdin/stdout no terminal atual, adicione --with-alias:

winapp run .\build\Debug --with-alias

Cenário B: Anexar um depurador a uma aplicação em execução

Inicia com winapp run, nota o PID, depois anexa o depurador do teu IDE.

winapp run .\build\Debug
# Output: Process ID: 12345

Depois, no teu IDE:

  • VS Code: Executar e Depurar → selecionar a configuração "Anexar" (ver configuração do IDE abaixo)
  • WinDbg: windbg -p 12345

Limitação: Vai perder qualquer código que seja executado antes de te conectares. Para depuração de arranque, use o Cenário D (create-debug-identity).

Cenário C: Registe a identidade e depois inicia via AUMID ou alias a partir do teu IDE

Use --no-launch para registar o pacote, depois inicie a aplicação através do AUMID (reportado por run) ou alias de execução a partir do seu IDE.

Passo 1: Registe o pacote sem lançar:

winapp run .\build\Debug --no-launch

Passo 2: Configura o teu IDE para lançar via AUMID ou pelo alias de execução (não diretamente pelo exe).

  • Lançamento com AUMID: Use o comando start shell:AppsFolder\<AUMID>. winapp run gera o AUMID quando a aplicação está registada.
  • Início com o alias: O alias deve ser definido no seu manifesto (Package.appxmanifest preferido, appxmanifest.xml também suportado).

Importante: Simplesmente lançar o exe na pasta de compilação não lhe dará identidade. A aplicação deve ser iniciada através da ativação AUMID ou do seu alias de execução. É assim que os pacotes de layout soltos funcionam – a identidade está ligada ao caminho de ativação, não ao ficheiro exe.

Cenário D: Iniciar a partir do seu IDE com identidade (depuração de arranque)

Esta é a melhor abordagem para depurar código de arranque com controlo total do IDE – o depurador do seu IDE controla o processo desde a primeira instrução, e o exe tem identidade independentemente de como for lançado.

winapp create-debug-identity .\build\Debug\myapp.exe

Agora inicia o exe da forma que quiseres — a partir do terminal, do F5 do VS Code, de um script. O exe tem identidade porque Windows registou um pacote sparse apontando diretamente para ele.

Como difere de winapp run: Com create-debug-identity, a identidade está ligada ao próprio exe (via Add-AppxPackage -ExternalLocation). Com winapp run, a identidade está ligada ao pacote de layout flexível — o aplicativo deve ser iniciado através de AUMID ou de um apelido. Isto faz de create-debug-identity a melhor escolha quando você precisa que o seu IDE inicie e depure diretamente o arquivo exe.

Esta é também a melhor abordagem para aplicações Electron onde o caminho do exe difere do diretório de origem.

Cenário E: Captura de saída de depuração e diagnóstico de falhas

Capturar OutputDebugString mensagens e exceções de primeira ocorrência integradas. O ruído do framework (WinUI, COM, rastreios internos do DirectX) é filtrado da consola para que apenas apareçam as mensagens de depuração da aplicação. Tudo ainda está escrito no ficheiro de registo para investigação completa.

Se a aplicação crashar, um minidump é capturado e analisado automaticamente:

winapp run .\build\Debug --debug-output

Em caso de falha, a saída inclui o tipo de exceção, a mensagem e o rastreamento de pilha com o ficheiro de origem e os números de linhas (resolvidos a partir dos PDBs no seu diretório de saída do build). As falhas geridas (.NET) são analisadas instantaneamente sem necessidade de ferramentas externas. Crashes nativos (C++/WinRT) mostram nomes e deslocamentos de módulos; adicionar --symbols para descarregar símbolos PDB para nomes completos de funções:

winapp run .\build\Debug --debug-output --symbols

Importante: Isto designa o winapp como depurador. Windows só permite um depurador por processo, por isso não pode também anexar Visual Studio, VS Code ou WinDbg.

Triagem de exceções suspensas em WinUI

A maioria dos crashes do WinUI começa dentro de um gestor de eventos XAML e surge como uma exceção armazenada (0xC000027B) que é reativada mais tarde pelo despachante, pelo que a pilha normal já não aponta para a causa real. Quando a aplicação que falhou é carregada Microsoft.UI.Xaml.dll, o winapp executa automaticamente uma etapa adicional de triagem que descodifica a exceção armazenada e a cadeia nativa de encaminhamento do XAML (Microsoft.UI.XamlCXcpDispatcherCoreMessagingXP → anfitrião do CLR). O resultado é anexado ao registo de depuração. Não é necessário nenhum flag — está ativado automaticamente para dumps do WinUI. Adicione --symbols para nomes de funções totalmente resolvidos na cadeia de despacho.

Para que isto funcione, o winapp captura o crash dump com o registo da exceção armazenada que provocou a terminação (e os respetivos parâmetros, que apontam para a matriz de exceções armazenadas), mantendo o contexto da thread de primeira ocorrência, de modo que a análise gerida padrão continua a recuperar o frame original do utilizador e a fase de triagem consegue localizar a exceção armazenada.

Este passe aloja o DbgEng com a extensão JavaScript WinDbg da equipa WinUI. O motor de depuração vem da NuGet; JsProvider.dll (o host JavaScript, não publicado no NuGet) é obtido à primeira utilização a partir do download oficial do WinDbg. Ambos estão associados a uma versão específica e são verificados antes de serem carregados — hashes de conteúdo SHA-512, além de uma verificação da assinatura Microsoft Authenticode em JsProvider.dll — e qualquer falha na verificação ignora a triagem, em vez de se carregar código não verificado. Tudo está armazenado em cache no diretório global do winapp, por isso as execuções posteriores ficam offline.

Se o seu ambiente impedir esses descarregamentos, instale o Debugging Tools for Windows (através do Windows SDK) ou defina WINAPP_DBGTOOLS_DIR para um diretório do depurador que contenha dbgeng.dll e JsProvider.dll. Quando WINAPP_DBGTOOLS_DIR está definido, é autoritativo — apenas esse diretório é consultado — e se estiver incompleto, o registo nomeia o componente em falta.

Quando a triagem tem sucesso, a consola mostra um veredicto de uma linha (o código/mensagem de erro da exceção armazenada). Quando não consegue executar, a consola indica isso, o registo explica porquê e a análise padrão de código gerido/nativo continua a ser executada.

A fase de triagem é executada num processo filho de curta duração, porque o processo principal do winapp já carregou o sistema dbghelp.dll e o moderno dbgeng.dll não se consegue associar em simultâneo com ele. A descodificação das estruturas de exceções armazenadas também requer símbolos do sistema operativo (combase.dll), que --symbols transfere do servidor público de símbolos da Microsoft; nas compilações cujos símbolos não são publicados nesse servidor, a triagem continua a identificar a exceção armazenada, mas não consegue expandi-la totalmente.

Configuração do IDE

Código VS

A extensão WinApp VS Code fornece um winapptipo de depuração personalizado que inicia a sua aplicação com identidade de pacote e liga o depurador — tudo com uma única pressão de F5. Instale-o a partir do Visual Studio Marketplace; o seu rastreador de origem e de problemas está disponível no repositório microsoft/WinAppVSCE.

Depuração F5 com um único toque e identidade

Adicionar uma winapp configuração de lançamento a .vscode/launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "winapp",
            "request": "launch",
            "name": "WinApp: Launch and Attach"
        }
    ]
}

Quando carregas em F5:

  1. A extensão analisa o espaço de trabalho em busca de diretórios de saída de compilação contendo ficheiros .exe.
  2. Selecionas a pasta de build para executar (ou defines inputFolder para saltar o prompt).
  3. Ele lança a sua aplicação via winapp run para lhe dar identidade ao pacote.
  4. Uma sessão de depuração secundária conecta-se ao processo em execução usando o depurador que especificou.

Depois de o depurador se conectar, obtém a experiência completa de depuração de VS Code — define pontos de interrupção clicando na caleira, percorre o código linha a linha (F10), entra nas funções (F11), inspeciona variáveis no painel de Variáveis e avalia expressões na Consola de Depuração. A aplicação corre com identidade de pacote em todo o processo, por isso as APIs dependentes da identidade comportam-se exatamente como se comportariam em produção.

Importante: O winapp tipo de depuração não constrói automaticamente o seu projeto. Depois de fazer alterações ao código, reconstrua antes de carregar em F5.

Automatizar builds com preLaunchTask

Para evitar esquecer de reconstruir, adicione um preLaunchTask que constrói o seu projeto antes de cada sessão de depuração:

  1. Defina uma tarefa de build em .vscode/tasks.json (exemplo para .NET):
    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build",
                "command": "dotnet",
                "type": "process",
                "args": ["build", "${workspaceFolder}"],
                "problemMatcher": "$msCompile"
            }
        ]
    }
    
  2. Refere-o no teu launch.json:
    {
        "type": "winapp",
        "request": "launch",
        "name": "WinApp: Launch and Attach",
        "preLaunchTask": "build"
    }
    

Propriedades de configuração

Property Tipo Predefinição Description
inputFolder cadeia (de caracteres) Caminho para a pasta de saída da build que contém os binários da tua app (por exemplo, ${workspaceFolder}/bin/Debug/net8.0-windows10.0.22621). Se não estiver definido, será solicitado que selecione uma pasta.
manifest cadeia (de caracteres) Caminho para um ficheiro manifesto do AppX (por exemplo, AppxManifest.xml, Package.appxmanifest, ou appxmanifest.xml). Se não estiver ativado, a CLI deteta automaticamente a partir da pasta de entrada ou do diretório atual.
debuggerType cadeia (de caracteres) coreclr Depurador subjacente para usar (coreclr, cppvsdbg, ou node).
workingDirectory cadeia (de caracteres) Pasta do Espaço de Trabalho Diretório de trabalho para o aplicativo.
args cadeia (de caracteres) Argumentos de linha de comandos para passar à aplicação.
outputAppxDirectory cadeia (de caracteres) Diretório de saída para o pacote de layout flexível. Por padrão, uma AppX pasta dentro da pasta de entrada.
port número 9229 (node apenas) A porta usada para o escutador Node.js --inspect e para a conexão de ligação. Override quando a porta padrão já estiver a ser usada.

Depuradores suportados

debuggerType Linguagem Prorrogação Obrigatória
coreclr (padrão) C# / .NET Kit de Desenvolvimento em C#
cppvsdbg C / C++ C/C++
node Node.js / Electron Incorporada

Exemplo para um projeto em C++:

{
    "type": "winapp",
    "request": "launch",
    "name": "WinApp: Launch C++ App",
    "debuggerType": "cppvsdbg"
}

Depuração de início com Criar uma Identidade de Depuração

Se precisar de depurar o código de arranque a partir da primeira instrução, a abordagem de anexar com F5 pode perder as instruções iniciais. Em vez disso, use o comando WinApp: Create Debug Identity a partir da Paleta de Comandos (Ctrl+Shift+P) para registar um pacote esparso para o seu executável, depois lance-o com o seu depurador padrão:

{
    "name": "Launch (with identity)",
    "type": "coreclr",
    "request": "launch",
    "program": "${workspaceFolder}/bin/Debug/net8.0-windows10.0.22621/myapp.exe"
}

Desde que create-debug-identity regista a identidade no próprio exe, a aplicação tem identidade independentemente da forma como é lançada — incluindo a partir de uma configuração padrão de lançamento do VS Code.

Anexar a um processo em execução

Se preferir lançar a partir winapp run do terminal e depois acoplar, use uma configuração padrão de união.

{
    "name": "Attach to Process",
    "type": "coreclr",
    "request": "attach",
    "processId": "${command:pickProcess}"
}

Para C++/Rust, use "type": "cppvsdbg" (MSVC) ou "type": "lldb" (LLDB):

{
    "name": "Attach (C++)",
    "type": "cppvsdbg",
    "request": "attach",
    "processId": "${command:pickProcess}"
}

Limpeza

Quando você terminar os testes, execute WinApp: Unregister Package da Command Palette para remover pacotes sideloaded de desenvolvimento sem sair do VS Code.