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á estiver usando Visual Studio para seu projeto empacotado, provavelmente não precisará do winapp para depuração. Visual Studio já manipula o registro do pacote, a identidade, a ativação do AUMID, a anexação do depurador e a depuração de código de ativação, tudo a partir do 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 Anexar ao PID após a inicialização, ou usar --no-launch e iniciar via apelido. Inicie diretamente do depurador do IDE — o arquivo exe possui identidade independente
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 completo do depurador do 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 exe está separado do resultado do build, por exemplo, em aplicativos Electron onde electron.exe reside 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 não é possível iniciar com AUMID e é necessário que o processo iniciado tenha identidade — create-debug-identity registra o exe de forma que ele tenha identidade, independentemente de como é 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 em seu manifesto (Package.appxmanifest preferencial, appxmanifest.xml também com suporte).

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 da IDE com identificação (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 solto – 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 saída de depuração e diagnósticos de falha

Capturar OutputDebugString mensagens e exceções de primeira chance em linha. O ruído do framework (logs internos do WinUI, COM, DirectX) é filtrado do console, garantindo que apenas as mensagens de depuração do aplicativo apareçam. 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 de PDBs na pasta de resultados da compilação). Falhas gerenciadas (.NET) são analisadas instantaneamente sem ferramentas externas. Falhas nativas (C++/WinRT) mostram os nomes e deslocamentos do módulo; adicione --symbols para baixar símbolos PDB para nomes completos das funções:

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

Importante: Isso anexa 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 stowed-exception no WinUI

A maioria dos travamentos 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 dispatcher, de modo que a pilha de chamadas normal não aponta mais para a causa real. Quando o aplicativo que falhou foi carregado Microsoft.UI.Xaml.dll, o winapp executa automaticamente uma etapa extra de triagem que decodifica a exceção armazenada e a cadeia de despacho nativa do XAML (Microsoft.UI.XamlCXcpDispatcherCoreMessagingXP → host do 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 fazer isso funcionar, o winapp captura o dump de falha com o registro da exceção stowed de terminação (e seus parâmetros, que apontam para a matriz de exceções stowed), 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 a etapa de triagem possa localizar a exceção stowed.

Esse passe hospeda dbgEng com a extensão WinDbg JavaScript da equipe WinUI. O mecanismo de depuração nativo (dbgeng.dll e amigos) vem do NuGet, e JsProvider.dll — o host de scripts JavaScript, que não está no NuGet — é obtido na primeira utilização diretamente do download oficial do WinDbg (somente algumas centenas de quilobytes necessárias são lidas, não o pacote completo). Como JsProvider.dll deve ter o mesmo build que o mecanismo — carregar um provedor incompatível faz o depurador travar na inicialização — ele fica vinculado ao pacote específico do WinDbg cujo build corresponde ao mecanismo do NuGet (e não à versão "current" contínua); depois de obtidos, os dois builds são comparados: qualquer incompatibilidade é rejeitada, e a triagem é pulada com um motivo claro, em vez de o processo falhar silenciosamente. Os pacotes do depurador têm versões fixadas e, antes que qualquer uma de suas DLLs nativas seja extraída e carregada, são conferidos contra um hash SHA-512 do conteúdo incorporado na compilação (e a extensão, contra um hash fixado); além disso, JsProvider.dll deve conter uma assinatura Microsoft Authenticode válida, verificada com checagem completa de revogação da cadeia de certificados (recorrendo a uma verificação apenas da assinatura quando os dados de revogação não puderem ser acessados offline, mas sempre rejeitando um certificado revogado). Os downloads são preparados para um arquivo temporário, verificado e, em seguida, publicados atomicamente no cache, de modo que uma execução simultânea nunca observa uma DLL parcialmente gravada ou não verificada. Em cada execução, os binários em cache são verificados novamente (confere-se se a assinatura JsProvider.dll e sua engine-build correspondem, e se as DLLs do mecanismo formam uma imagem PE válida), de modo que um cache truncado ou corrompido se recupere automaticamente ao readquirir os arquivos, em vez de falhar a cada execução. Juntos, isso significa que um feed espelhado ou comprometido não pode substituir binários alterados – qualquer falha ignora a triagem em vez de carregar código não verificado. Tudo é armazenado em cache no diretório global do winapp, portanto, as execuções subsequentes 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 a variável de WINAPP_DBGTOOLS_DIR ambiente para um diretório de depurador que já contém dbgeng.dll e JsProvider.dll. Quando WINAPP_DBGTOOLS_DIR é definido, é autoritativo – somente que o diretório é consultado – portanto, se ele estiver incompleto, o log nomeia o componente ausente específico (dbgeng.dll e/ou JsProvider.dll) em vez de sugerir que você defina uma variável que já está definida. Quando a triagem for bem-sucedida, o console exibirá um veredito em uma única linha (o código/mensagem de erro da exceção armazenada); quando os binários não puderem ser obtidos, a etapa de triagem será ignorada (a análise gerenciada/nativa padrão ainda será executada), o console informará isso, e o log explicará o motivo.

A etapa de triagem é executada em um processo filho de curta duração. Isso é necessário: o processo principal do winapp carrega o sistema dbghelp.dll durante a captura e a análise do despejo, e o mecanismo dbgeng.dll moderno não pode se associar a essa cópia antiga e já residente – um novo processo dá ao mecanismo um estado de carregador limpo. A decodificação das estruturas de exceção stowed também requer símbolos do sistema operacional (combase.dll), que --symbols baixa do servidor público de símbolos da Microsoft; em builds cujos símbolos não são publicados nesse servidor, a etapa de triagem ainda identifica a exceção stowed, 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 F5 de um toque, com identidade

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 da construção que contêm 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 filial é anexada ao processo em execução usando o depurador que você especificou.

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 reconstruir, adicione um preLaunchTask que construa 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 for definido, a CLI detectará automaticamente da pasta de entrada ou do diretório atual.
debuggerType cadeia coreclr Depurador subjacente a ser usado (coreclr, cppvsdbg ou node).
workingDirectory cadeia pasta de 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 de layout flexível. O padrão é uma AppX pasta dentro da pasta de entrada.
port número 9229 (node somente) A porta usada para o escutador Node.js --inspect e a conexão de anexação. Substitua 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"
}

Debugging de inicialização com Create Debug Identity

Se você precisar depurar o código de inicialização desde a primeira instrução, o método de conexão com F5 poderá omitir as instruções iniciais. 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 de testar, execute WinApp: Desregistrar Pacote na Paleta de Comandos para remover pacotes de desenvolvimento sideloaded sem sair do VS Code.