Depuração com a identidade do pacote

Muitas APIs do Windows (notificações por push, tarefas em segundo plano, destino de compartilhamento, tarefas de inicialização, APIs de IA do Windows) exigem que seu aplicativo tenha identidade de pacote. Durante o desenvolvimento, você não deseja criar um instalador MSIX completo sempre que testar – o winapp fornece dois comandos para fornecer a identidade do aplicativo em tempo real.

Usando Visual Studio com um projeto de empacotamento? Se você já usa o Visual Studio para seu projeto empacotado, provavelmente não precisa do winapp para depuração. O Visual Studio já lida com o registro de pacotes, identidade, ativação do AUMID, conexão do depurador e depuração do código de ativação — tudo a partir da tecla F5. Ele também oferece Depuração → Outros Destinos de Depuração → Depurar Pacote de Aplicativo Instalado para cenários avançados. Os fluxos de trabalho abaixo são mais úteis para usuários do VS Code, fluxos de trabalho baseados em terminal e estruturas 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 ele registra Pacote completo de layout flexível (toda a pasta) Pacote esparso (exe único)
Como o aplicativo é iniciado Iniciado pelo winapp (alias de ativação ou execução do AUMID) Inicie o exe por conta própria (linha de comando, IDE etc.)
Simula a instalação do MSIX Sim – mais próximo do comportamento de produção Não – somente identidade dispersa
Os arquivos permanecem no local Copiado para um diretório de layout do AppX Sim — exe permanece em seu caminho original
Escopo de identidade Conteúdo de pasta inteira (exe, DLLs, ativos) Executável único
Amigável ao depurador Anexe ao PID após a inicialização ou use --no-launch e inicie via alias Inicie diretamente do depurador da sua IDE — o executável terá identidade independentemente
Suporte ao aplicativo de console --with-alias mantém stdin/stdout no terminal Executar o exe diretamente no terminal
Mais adequado para A maioria das estruturas (.NET, C++, Rust, Flutter, Tauri) Electron ou quando você precisar de controle total do depurador da IDE (F5)

Quando usar qual

Padrão: winapp run

Use o winapp run para a maioria dos fluxos de trabalho de desenvolvimento. Ele simula uma instalação msix real – seu aplicativo obtém a mesma identidade, funcionalidades e associações de arquivos que ele teria em produção.

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

Use create-debug-identity quando:

  • Seu executável é separado da sua saída de compilação — por exemplo, aplicativos Electron onde electron.exe reside em node_modules/
  • Você precisa depurar o código de inicialização e não pode anexar um depurador rápido o suficiente após a inicialização do AUMID
  • Com alguns depuradores onde você não pode iniciar com AUMID e precisa de identidade no processo iniciado — create-debug-identity registra o executável para que ele tenha identidade independentemente de como for iniciado
  • Você está testando especificamente o comportamento do pacote esparso (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: basta executar com a identidade

O fluxo de trabalho mais simples : compilar, executar com identidade, concluído.

winapp run .\build\Debug

O Winapp registra a pasta como um pacote de layout flexível e inicia o aplicativo. As APIs que exigem identidade funcionam imediatamente. Isso abrange a maioria dos cenários de desenvolvimento e teste.

Para aplicativos de console que precisam de stdin/stdout no terminal atual, adicione --with-alias:

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

Cenário B: anexar um depurador a um aplicativo em execução

Inicie com winapp run, anote o PID e, em seguida, anexe o depurador do IDE.

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

Em seguida, no seu IDE:

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

Limitação: Você perderá qualquer código executado antes de anexar. Para depuração de inicialização, use o Cenário D (create-debug-identity).

Cenário C: Registrar identidade e, em seguida, iniciar por meio do AUMID ou alias do IDE

Use --no-launch para registrar o pacote e, em seguida, inicie o aplicativo por meio de seu AUMID (relatado por run) ou alias de execução do seu IDE.

Etapa 1: Registre o pacote sem iniciar:

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

Etapa 2: Configure o IDE para iniciar por meio do AUMID ou do alias de execução (não o exe diretamente).

  • Iniciando com a AUMID: use o comando start shell:AppsFolder\<AUMID>. winapp run gera o AUMID quando o aplicativo é registrado.
  • Iniciando com o alias: o alias deve ser definido no seu manifesto (Package.appxmanifest preferencial, appxmanifest.xml também suportado).

Importante: Simplesmente iniciar o exe na pasta de build não lhe dará identidade. O aplicativo deve ser iniciado por meio da ativação do AUMID ou seu alias de execução. É assim que os pacotes de layout flexível funcionam – a identidade está vinculada ao caminho de ativação, não ao arquivo exe.

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

Essa é a melhor abordagem para depurar o código de inicialização com controle IDE completo – o depurador do IDE controla o processo desde a primeira instrução e o exe tem identidade, independentemente de como ele é iniciado.

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

Agora, inicie o exe da maneira que você quiser – do terminal, do F5 do VS Code, a partir de um script. O exe tem identidade porque Windows registrou um pacote sparse apontando diretamente para ele.

Como ela difere de winapp run: Com create-debug-identity, a identidade está vinculada ao exe em si (via Add-AppxPackage -ExternalLocation). Com winapp run, a identidade está vinculada ao pacote de layout flexível — o aplicativo deve ser iniciado por meio do AUMID ou de um alias. Isso faz create-debug-identity a melhor escolha quando você precisa de seu IDE para iniciar e depurar o exe diretamente.

Essa também é a melhor abordagem para aplicativos Electron em que o caminho exe difere do diretório de origem.

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

Capturar mensagens OutputDebugString e exceções de primeira chance em linha. Ruídos do framework (WinUI, COM, rastreamentos internos do DirectX) são filtrados do console para que apenas as mensagens de depuração do seu aplicativo sejam exibidas. Tudo ainda é registrado no arquivo de registro para investigação completa.

Se o aplicativo falhar, um minidump será 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 arquivo de origem e os números de linha (resolvidos a partir dos PDBs na pasta de saída da sua compilação). Falhas gerenciadas (.NET) são analisadas instantaneamente sem ferramentas externas. Falhas nativas (C++/WinRT) mostram nomes de módulos e deslocamentos; adicione --symbols para baixar os símbolos PDB para obter os nomes completos das funções:

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

Importante: isso anexa o winapp como depurador. Windows permite apenas um depurador por processo, portanto, você não pode anexar também Visual Studio, VS Code ou WinDbg.

Triagem de exceções armazenadas do WinUI

A maioria das falhas do WinUI começa dentro de um manipulador de eventos XAML e se manifesta como uma exceção armazenada (0xC000027B) que é relançada posteriormente pelo despachante, de modo que a pilha normal não aponta mais para a causa real. Quando o aplicativo com falha carrega Microsoft.UI.Xaml.dll, o winapp executa automaticamente uma passagem de triagem extra que decodifica a exceção armazenada e a cadeia de despacho XAML nativa (Microsoft.UI.XamlCXcpDispatcherCoreMessagingXP → host CLR). O resultado é adicionado ao log de depuração. Nenhum sinalizador é necessário — ele é habilitado automaticamente para despejos do WinUI. Adicione --symbols para nomes de função totalmente resolvidos na cadeia de despacho.

Para que isso funcione, o winapp captura o despejo de memória com o registro da exceção armazenada que causou a falha (e seus parâmetros, que apontam para a matriz de exceções armazenadas), mantendo o contexto da thread de primeira chance, de modo que a análise gerenciada padrão ainda recupere seu frame de usuário original e e a passagem de triagem possa localizar a exceção armazenada.

Esta passagem hospeda o DbgEng com a extensão JavaScript WinDbg da equipe WinUI. O mecanismo de depuração vem do NuGet; JsProvider.dll (o host JavaScript, não publicado no NuGet) é obtido no primeiro uso a partir do download oficial do WinDbg. Ambos têm suas versões fixadas e são verificados antes do carregamento — hashes de conteúdo SHA-512, além de uma verificação de assinatura Microsoft Authenticode em JsProvider.dll — e qualquer falha na verificação ignora a triagem em vez de carregar o código não verificado. Tudo é armazenado em cache no diretório global do winapp, portanto, as execuções posteriores estão offline.

Se o ambiente bloquear esses downloads, instale as Ferramentas de Depuração para Windows (por meio do SDK do Windows) ou defina WINAPP_DBGTOOLS_DIR como um diretório de depurador contendo dbgeng.dll e JsProvider.dll. Quando WINAPP_DBGTOOLS_DIR é definido, ele é autoritativo — somente que o diretório é consultado — e, se estiver incompleto, o log nomeia o componente ausente.

Quando a triagem é bem-sucedida, o console exibe um resultado em uma linha (o código/mensagem de erro da exceção armazenada). Quando não é possível executá-lo, o console informa isso, o log explica o motivo, e a análise padrão de código gerenciado/nativo ainda é executada.

A triagem é executada em um 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 pode ser vinculado a ele. A decodificação das estruturas de exceção armazenadas também precisa de símbolos do sistema operacional (combase.dll), que --symbols baixa do servidor de símbolos públicos da Microsoft; em compilações cujos símbolos não estão publicados lá, a triagem ainda identifica a exceção armazenada, mas não consegue expandi-la completamente.

Configuração do IDE

VS Code

A extensão WinApp VS Code fornece um winapp tipo de depuração personalizado que inicia seu aplicativo com identidade de pacote e anexa o depurador — tudo isso com um único pressionamento de F5. Instale-o no Visual Studio Marketplace; seu rastreador de origem e problema reside no repositório microsoft/WinAppVSCE.

Depuração com um único toque de F5 com identificação

Adicione uma winapp configuração de inicialização a .vscode/launch.json:

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

Quando você pressiona F5:

  1. A extensão verifica seu espaço de trabalho em busca de diretórios de saída de compilação que contenham arquivos .exe.
  2. Selecione a pasta de build a ser executada (ou defina inputFolder para ignorar o prompt).
  3. Ele inicia seu aplicativo via winapp run para atribuir a identidade de pacote.
  4. Uma sessão de depuração filha se conecta ao processo em execução usando o depurador especificado.

Depois que o depurador é anexado, você obtém a experiência completa de depuração do VS Code – defina pontos de interrupção clicando na sarjeta, percorra o código linha a linha (F10), entre em funções (F11), inspecione as variáveis no painel Variáveis e avalie as expressões no Console de Depuração. O aplicativo é executado com a identidade do pacote em toda parte, de modo que as APIs dependentes de identidade se comportam exatamente da mesma forma que em produção.

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

Automatizar compilações com preLaunchTask

Para evitar esquecer de recompilar, adicione um preLaunchTask que compile seu projeto antes de cada sessão de depuração:

  1. Definir uma tarefa de build em .vscode/tasks.json (por exemplo, .NET):
    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build",
                "command": "dotnet",
                "type": "process",
                "args": ["build", "${workspaceFolder}"],
                "problemMatcher": "$msCompile"
            }
        ]
    }
    
  2. Faça referência a ele em seu launch.json:
    {
        "type": "winapp",
        "request": "launch",
        "name": "WinApp: Launch and Attach",
        "preLaunchTask": "build"
    }
    

Propriedades de configuração

Propriedade Tipo Padrão Description
inputFolder cadeia Caminho para a pasta de saída de build que contém os binários do aplicativo (por exemplo, ${workspaceFolder}/bin/Debug/net8.0-windows10.0.22621). Se não estiver definido, será solicitado que você selecione uma pasta.
manifest cadeia Caminho para um arquivo de manifesto AppX (por exemplo, AppxManifest.xml, Package.appxmanifestou appxmanifest.xml). Se não estiver definido, a CLI detecta automaticamente a partir da pasta de entrada ou do diretório atual.
debuggerType cadeia coreclr Depurador subjacente a ser usado (coreclr, cppvsdbg ou node).
workingDirectory cadeia pasta workspace Diretório de trabalho para o aplicativo.
args cadeia Argumentos de linha de comando a serem passados para o aplicativo.
outputAppxDirectory cadeia Diretório de saída para o pacote loose-layout. O padrão é uma AppX pasta dentro da pasta de entrada.
port número 9229 (node somente) A porta usada para o listener --inspect do Node.js e a conexão de anexação. Substitui quando a porta padrão já estiver em uso.

Depuradores com suporte

debuggerType Linguagem Extensão necessária
coreclr (padrão) C# /.NET Kit de Desenvolvimento do C#
cppvsdbg C/C++ C/C++
node Node.js/Electron Interna

Exemplo para um projeto C++:

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

Depuração de inicialização com Criar Identidade de Depuração

Se você precisar depurar o código de inicialização desde a primeira instrução, a abordagem de anexação com F5 pode não detectar o código inicial. Em vez disso, use o comando WinApp: Criar Identidade de Depuração da Paleta de Comandos (Ctrl+Shift+P) para registrar um pacote esparso para o executável e inicie-o com o depurador padrão:

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

Como create-debug-identity registra a identidade no próprio exe, o aplicativo tem identidade independentemente de como ele é iniciado , inclusive de uma configuração de inicialização padrão do VS Code.

Anexar a um processo em execução

Se você preferir iniciar pelo winapp run do terminal e em seguida anexar, use uma configuração padrão para anexar:

{
    "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 terminar os testes, execute WinApp: Cancelar registro do pacote na Paleta de Comandos para remover pacotes de desenvolvimento instalados por fora sem sair do VS Code.