Debug con l'identità del pacchetto

Molte API di Windows (notifiche push, attività in background, destinazione di condivisione, attività di avvio, API di intelligenza artificiale Windows) richiedono che l'app abbia package identity. Durante lo sviluppo, non vuoi creare un programma di installazione MSIX completo ogni volta che esegui il test. Winapp fornisce due comandi per assegnare all'app l'identità in tempo reale.

Uso di Visual Studio con un progetto di creazione di pacchetti? Se usi già Visual Studio per il progetto in pacchetto, probabilmente non hai bisogno di winapp per il debug. Visual Studio gestisce già la registrazione del pacchetto, l'identità, l'attivazione AUMID, l'allegato del debugger e il debug del codice di attivazione, tutti da F5. Offre anche Debug → Altre Destinazioni di Debug → Debug Pacchetto App Installato per scenari avanzati. I flussi di lavoro seguenti sono più utili per gli utenti di VS Code, i flussi di lavoro basati su terminale e i framework che VS non include in modo nativo (Rust, Flutter, Tauri, Electron, plain C++).

Due approcci: winapp run vs create-debug-identity

winapp run create-debug-identity
Cosa registra Pacchetto di layout libero completo (intera cartella) Pacchetto ridotto (singolo EXE)
Modalità di avvio dell'app Avviato da winapp (attivazione AUMID o alias di esecuzione) Avviare l'exe manualmente (riga di comando, IDE e così via)
Simula l'installazione di MSIX Sì , più vicino al comportamento di produzione No — solo identità sparse
I file rimangono sul posto Copiato in una directory di layout AppX Sì — exe rimane nel suo percorso originale
Ambito di identità Contenuto dell'intera cartella (exe, DLL, assets) Singolo eseguibile
Debugger-friendly Collegarsi al PID dopo l'avvio, oppure usare --no-launch e poi avviare tramite alias Avvia direttamente dal debugger dell'IDE: l'exe mantiene un'identità indipendentemente dal contesto.
Supporto delle app console --with-alias mantiene stdin/stdout nel terminale Eseguire exe direttamente nel terminale
Migliore per Maggior parte dei framework (.NET, C++, Rust, Flutter, Tauri) Electron o quando è necessario il controllo completo del debugger IDE (F5)

Quando usare quale

Impostazione predefinita: winapp run

Usare winapp run per la maggior parte dei flussi di lavoro di sviluppo. Simula un'installazione MSIX reale: l'app ottiene la stessa identità, funzionalità e associazioni di file che avrebbe in produzione.

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

Usare create-debug-identity quando:

  • Il file exe è separato dall'output di compilazione — ad esempio, nelle app Electron dove electron.exe si trova in node_modules/
  • È necessario eseguire il debug del codice di avvio e non è possibile collegare un debugger abbastanza velocemente dopo l'avvio dell'AUMID
  • Con alcuni debugger in cui non è possibile avviare con AUMID ed è necessaria l'identità nel processo avviato, create-debug-identity registra l'exe in modo che abbia un'identità indipendentemente dal modo in cui viene avviata
  • Si sta testando il comportamento del pacchetto sparse in modo specifico (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

Scenari di debug

Scenario A: Procedi semplicemente con l'identità

Il flusso di lavoro più semplice, ovvero compilare, eseguire con identità, operazione completata.

winapp run .\build\Debug

Winapp registra la cartella come pacchetto di layout libero e avvia l'app. Le API che richiedono identità funzionano immediatamente. Ciò riguarda la maggior parte degli scenari di sviluppo e test.

Per le app console che richiedono stdin/stdout nel terminale corrente, aggiungere --with-alias:

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

Scenario B: Collegare un debugger a un'app in esecuzione

Avviare con winapp run, prendere nota del PID, quindi collegare il debugger dell'IDE.

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

Quindi nel tuo IDE:

  • VS Code: Esegui e debugga → seleziona la configurazione "Allega" (vedi configurazione dell'IDE di seguito)
  • WinDbg: windbg -p 12345

Limitazione: Si perderà qualsiasi codice eseguito prima di collegarsi. Per il debug di avvio, usare scenario D (create-debug-identity).

Scenario C: Registrare l'identità, quindi avviare tramite AUMID o alias dall'IDE

Usare --no-launch per registrare il pacchetto, quindi avviare l'app tramite l'AUMID (segnalato da run) o l'alias di esecuzione dall'IDE.

Passaggio 1: Registrare il pacchetto senza avviare:

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

Passaggio 2: Configurare l'IDE per l'avvio tramite l'AUMID o l'alias di esecuzione (non direttamente il file exe).

  • Avvio con AUMID: usare il comando start shell:AppsFolder\<AUMID>. winapp run restituisce l'AUMID quando l'app viene registrata.
  • Avvio con l'alias: l'alias deve essere definito nel manifest (Package.appxmanifest preferito, appxmanifest.xml anche supportato).

Importante: Il semplice avvio dell'exe nella cartella build non fornirà un'identità. L'app deve essere avviata tramite l'attivazione AUMID o il relativo alias di esecuzione. Questo è il funzionamento dei pacchetti di layout separati: l'identità è associata al percorso di attivazione, non al file exe.

Scenario D: Avviare dall'IDE con identità (debug di avvio)

Questo è l'approccio migliore per il debug del codice di avvio con controllo IDE completo : il debugger dell'IDE controlla il processo dalla prima istruzione e l'exe ha identità indipendentemente dal modo in cui viene avviata.

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

Avviare ora l'exe in qualsiasi modo, dal terminale, da F5 di VS Code, da uno script. L'exe ha un'identità perché Windows ha registrato un pacchetto sparse che punta direttamente ad esso.

Come differisce da winapp run: Con create-debug-identity, l'identità è associata all'exe stesso (tramite Add-AppxPackage -ExternalLocation). Con winapp run, l'identità è associata al pacchetto di layout libero. L'app deve essere avviata tramite AUMID o un alias. Ciò rende create-debug-identity la scelta migliore quando è necessario l'IDE per avviare ed eseguire direttamente il debug dell'exe.

Questo è anche l'approccio migliore per le app Electron in cui il percorso exe è diverso dalla directory di origine.

Scenario E: Acquisire l'output di debug e la diagnostica degli arresti anomali

Acquisire OutputDebugString i messaggi e le eccezioni first-chance inline. Il disturbo del framework (tracce interne WinUI, COM, DirectX) viene filtrato dalla console in modo che vengano visualizzati solo i messaggi di debug dell'app. Tutto è ancora scritto nel file di log per l'analisi completa.

Se l'app si arresta in modo anomalo, un minidump viene acquisito e analizzato automaticamente:

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

In caso di arresto anomalo, l'output include il tipo di eccezione, il messaggio e la traccia dello stack con numeri di riga e file di origine (risolti dai file PDB nella cartella di output della compilazione). I crash gestiti (.NET) vengono analizzati immediatamente senza bisogno di strumenti esterni. Gli crash nativi (C++/WinRT) visualizzano i nomi dei moduli e gli offset; aggiungere --symbols per scaricare i simboli PDB per i nomi delle funzioni completi:

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

Importante: In questo modo winapp viene collegato come debugger. Windows consente un solo debugger per processo, quindi non puoi collegare anche Visual Studio, VS Code o WinDbg.

Triage delle stowed exception di WinUI

La maggior parte degli arresti anomali di WinUI inizia all'interno di un handler di eventi XAML e si manifesta come eccezione archiviata (0xC000027B), che viene sollevata nuovamente in seguito dal dispatcher, quindi la normale analisi dello stack non indica più la causa reale. Quando è stata caricata l'app che si era arrestata in modo anomalo Microsoft.UI.Xaml.dll, winapp esegue automaticamente un passaggio di triage aggiuntivo che decodifica l'eccezione archiviata e la catena di dispatch XAML nativa (Microsoft.UI.XamlCXcpDispatcherCoreMessagingXP → host CLR). Il risultato viene aggiunto al log di debug. Non è necessario alcun flag: viene abilitato automaticamente per i dump di WinUI. Aggiungi --symbols per i nomi di funzione completamente risolti nella catena di dispatch.

Per far funzionare questo meccanismo, winapp acquisisce il dump di arresto anomalo con il record dell'eccezione stowed terminale (e i relativi parametri, che puntano all'array delle eccezioni stowed), mantenendo al contempo il contesto del thread di first chance, in modo che l'analisi gestita standard possa ancora recuperare il frame utente originale and il passaggio di triage possa individuare l'eccezione stowed.

Questo passaggio ospita DbgEng con l'estensione JavaScript WinDbg del team WinUI. Il motore di debug proviene da NuGet; JsProvider.dll (l'host JavaScript, non pubblicato su NuGet) viene scaricato al primo utilizzo dal download ufficiale di WinDbg. Entrambi sono bloccati a una versione specifica e verificati prima del caricamento — tramite hash di contenuto SHA-512, oltre a un controllo della firma Microsoft Authenticode su JsProvider.dll — e qualsiasi errore di verifica comporta l’omissione della fase di triage anziché il caricamento di codice non verificato. Tutti gli elementi vengono memorizzati nella cache nella directory globale winapp, quindi le esecuzioni successive sono offline.

Se l'ambiente blocca tali download, installare Gli strumenti di debug per Windows (tramite Windows SDK) o impostare su WINAPP_DBGTOOLS_DIR una directory del debugger contenente dbgeng.dll e JsProvider.dll. Quando WINAPP_DBGTOOLS_DIR è impostato, ha valore autoritativo — viene consultata solo quella directory — e, se è incompleto, il log indica il componente mancante.

Quando il triage riesce, la console mostra un verdetto su una sola riga (il codice/messaggio di errore dell'eccezione archiviata). Quando non può essere eseguito, la console lo segnala, il log ne spiega il motivo e l'analisi gestita/nativa standard viene comunque eseguita.

La fase di triage viene eseguita in un processo figlio di breve durata, perché il processo principale di winapp ha già caricato dbghelp.dll di sistema e il moderno dbgeng.dll non può effettuare il binding insieme ad esso. La decodifica delle strutture delle eccezioni archiviate richiede anche i simboli del sistema operativo (combase.dll), che --symbols scarica dal server pubblico dei simboli Microsoft; nelle build i cui simboli non sono pubblicati lì, il triage identifica comunque l'eccezione archiviata ma non può espanderla completamente.

Configurazione dell'IDE

VS Code

L'estensione WinApp VS Code fornisce un tipo di debug personalizzatowinapp che avvia l'app con l'identità del pacchetto e collega il debugger, tutto da una singola pressione F5. Installarlo dal marketplace di Visual Studio; il relativo tracker di origine e problema è attivo nel repository microsoft/WinAppVSCE.

Debug con un solo tocco del tasto F5 con supporto per l'identità

Aggiungere una winapp configurazione di avvio a .vscode/launch.json:

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

Quando si preme F5:

  1. L'estensione analizza l'area di lavoro per individuare le directory di output di compilazione contenenti .exe file.
  2. Selezionare la cartella di compilazione da eseguire o impostare inputFolder per ignorare il prompt.
  3. Avvia l'app tramite winapp run per conferirgli l'identità del pacchetto.
  4. Una sessione di debug secondaria si collega al processo in esecuzione usando il debugger assegnato.

Una volta collegato il debugger, si ottiene l'esperienza di debug completa di VS Code, ovvero impostare i punti di interruzione facendo clic sulla barra, passando attraverso la riga di codice per riga (F10), eseguire l'istruzione in funzioni (F11), esaminare le variabili nel riquadro Variabili e valutare le espressioni nella console di debug. L'app funziona con l'identità del pacchetto in tutto e per tutto, quindi le API che dipendono dall'identità si comportano esattamente come in produzione.

Importante: Il winapp tipo di debug non compila automaticamente il progetto. Dopo aver apportato modifiche al codice, ricompilare prima di premere F5.

Automatizzare le compilazioni con preLaunchTask

Per evitare di dimenticare di ricompilare, aggiungere un oggetto preLaunchTask che compila il progetto prima di ogni sessione di debug:

  1. Definire un'attività di compilazione in .vscode/tasks.json (ad esempio per .NET):
    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build",
                "command": "dotnet",
                "type": "process",
                "args": ["build", "${workspaceFolder}"],
                "problemMatcher": "$msCompile"
            }
        ]
    }
    
  2. Farvi riferimento in launch.json:
    {
        "type": "winapp",
        "request": "launch",
        "name": "WinApp: Launch and Attach",
        "preLaunchTask": "build"
    }
    

Proprietà di configurazione

Proprietà TIPO Default Description
inputFolder string Percorso della cartella di output della build contenente i file binari dell'applicazione, ad esempio ${workspaceFolder}/bin/Debug/net8.0-windows10.0.22621. Se non è impostato, verrà richiesto di selezionare una cartella.
manifest string Percorso di un file manifesto AppX (ad esempio, AppxManifest.xml, Package.appxmanifesto appxmanifest.xml). Se non è impostato, il CLI rileva automaticamente dalla cartella di input o dalla directory corrente.
debuggerType string coreclr Debugger sottostante da usare (coreclr, cppvsdbgo node).
workingDirectory string Cartella dell'area di lavoro Directory di lavoro per l'applicazione.
args string Argomenti della riga di comando da passare all'applicazione.
outputAppxDirectory string Directory di output per il pacchetto di layout libero. L'impostazione predefinita è una AppX cartella all'interno della cartella di input.
port Numero 9229 (node solo) Porta utilizzata per il listener di Node.js --inspect e la connessione di attacco. Eseguire l'override quando la porta predefinita è già in uso.

Debugger supportati

debuggerType Language Estensione richiesta
coreclr (impostazione predefinita) C# /.NET Kit di sviluppo C#
cppvsdbg C/C++ C/C++
node Node.js/Electron Built-in

Esempio per un progetto C++:

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

Esecuzione del debug all'avvio con Create Debug Identity

Se è necessario eseguire il debug del codice di avvio dalla prima istruzione, l'approccio di collegamento F5 potrebbe perdere il codice iniziale. Usare invece il comando WinApp: Create Debug Identity () dal riquadro comandi (Ctrl+Shift+P) per registrare un pacchetto sparse per il file eseguibile, quindi avviarlo con il debugger standard:

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

Poiché create-debug-identity registra l'identità nell'exe stesso, l'app ha un'identità indipendentemente dal modo in cui viene avviata, incluso da una configurazione di avvio standard di VS Code.

Connettersi a un processo in esecuzione

Se si preferisce avviare con winapp run dal terminale e quindi collegarsi, usare una configurazione di collegamento standard:

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

Per C++/Rust, usare "type": "cppvsdbg" (MSVC) o "type": "lldb" (LLDB):

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

Pulizia

Al termine dei test, eseguire WinApp: Deregistrare pacchetto dalla Palette dei comandi per rimuovere i pacchetti di sviluppo caricati lateralmente senza uscire da VS Code.