Debuggare un bug che si presenta solo su una macchina senza Visual Studio

Un bug si riproduce sul server di test e non sul tuo laptop. Il server di test non ha Visual Studio, e installarci sopra un IDE completo solo per mettere un breakpoint non è un’opzione. Il debug remoto serve esattamente per questo caso. Un piccolo programma standalone gira sulla macchina di destinazione, il tuo Visual Studio locale si collega ad esso via rete, e ottieni breakpoint e ispezione delle variabili su un processo che non gira da nessuna parte vicino alla tua scrivania.

Ci sono tre passaggi: avviare il debugger remoto sulla destinazione, agganciarsi da Visual Studio, caricare i simboli giusti. Ognuno fallisce in un modo tutto suo. Dopo questi arrivano le due destinazioni remote che incontrerai più spesso nella pratica: un processo dentro un container Docker e un’app su Azure App Service.

Come installare e avviare il debugger remoto di Visual Studio (msvsmon)

Il programma si chiama msvsmon.exe, il Visual Studio Remote Debugger. Puoi portarlo sulla macchina di destinazione in due modi.

Se la destinazione ha già Visual Studio Community, Professional o Enterprise installato, msvsmon.exe è già presente, sotto <cartella di installazione di Visual Studio>\Common7\IDE\Remote Debugger\x64\ (o x86\, a seconda dell’architettura che stai debuggando). Avvialo direttamente.

Altrimenti, scarica il pacchetto standalone dei remote tools dalla pagina dei remote tools di Microsoft per la tua versione di Visual Studio, e prendi il suo aggiornamento più recente. La compatibilità funziona in una sola direzione: i remote tools più nuovi funzionano con un Visual Studio più vecchio, ma i remote tools più vecchi possono rifiutare un Visual Studio più nuovo. Scegli l’architettura del sistema operativo di destinazione (x86, x64 o ARM64), non quella dell’app che stai debuggando.

Il primo avvio apre una configurazione guidata che aggiunge una regola al Windows Firewall per il tipo di rete su cui ti trovi (dominio, privata o pubblica). Alla fine, la finestra del Remote Debugger mostra un nome server e una porta. È l’indirizzo che digiterai in Visual Studio. Lascia la finestra aperta: chiuderla (File > Exit) termina la sessione.

Porte e autenticazione del debugger remoto: cosa blocca la connessione

La regola firewall creata dalla configurazione guidata apre solo la porta TCP in entrata, e quella porta cambia con la versione di Visual Studio. È la 4026 per Visual Studio 2022; le versioni precedenti usano numeri diversi. Se la destinazione sta dietro un firewall che la configurazione guidata non ha toccato, come un apparato aziendale o un security group cloud, apri tu stesso quella porta specifica. Indovinare “la porta del debugger” senza controllare la tua versione fa solo perdere tempo.

UDP 3702 in uscita è opzionale. Permette alla destinazione di comparire nel selettore Find di Visual Studio. Senza, puoi comunque connetterti: digiti l’indirizzo a mano.

La modalità di autenticazione deve combaciare su entrambi i lati. Per impostazione predefinita il debugger remoto usa la Windows Authentication, quindi l’account Windows che esegue Visual Studio ha bisogno del permesso sul debugger remoto. Concedilo da Tools > Permissions nella finestra del Remote Debugger (servono diritti da amministratore), oppure avvia msvsmon da riga di comando con l’account già autorizzato:

1
msvsmon /allow user@computer

Passare a No Authentication (Tools > Options nella finestra del Remote Debugger) salta tutto questo, ed è allettante su una VM usa e getta. Fallo solo su una rete di cui ti fidi completamente. Chiunque raggiunga quella porta può agganciarsi a qualsiasi processo in esecuzione sotto lo stesso account: nessun prompt, nessuna password.

Come agganciarsi a un processo remoto da Visual Studio

Con il debugger remoto avviato e raggiungibile:

  1. In Visual Studio, apri Debug > Attach to Process (Ctrl+Alt+P).
  2. Imposta Connection type su Remote (Windows).
  3. In Connection target, digita l’indirizzo nel formato mostrato dalla finestra del debugger remoto, di solito <nome-macchina>:<porta>. Se il nome macchina non risolve, usa l’IP: 10.0.0.15:4026.
  4. Clicca Refresh per scaricare la lista dei processi dalla macchina remota, poi trova e seleziona il tuo processo. Se non gira sotto il tuo account, spunta Show processes from all users. Visual Studio mostra un avviso di sicurezza prima di agganciarti a un processo di qualcun altro: leggilo invece di chiuderlo subito.
  5. Lascia Code type su Automatic. L’eccezione è un processo con codice misto in cui l’attach fallisce in silenzio per un linguaggio: scegli quel linguaggio esplicitamente e riprova, e otterrai un errore specifico invece di niente.
  6. Clicca Attach.

Per un’app ASP.NET ospitata su IIS, il processo che ti serve è w3wp.exe. Per un’app .NET con il proprio server Kestrel, è dotnet.exe o il nome dell’eseguibile dell’app. IIS fa spesso girare più w3wp.exe identici fianco a fianco. La colonna Command Line nella lista dei processi è quella che li distingue.

Come risolvere “no symbols loaded” nel debug remoto

Agganciarsi non significa poter già debuggare. Apri Debug > Windows > Modules e guarda la colonna Symbol Status per il tuo binario. Un cerchietto rosso vuoto al posto di un breakpoint pieno dice la stessa cosa dal lato dell’editor: il debugger non ha simboli con cui mappare quel breakpoint.

Nella pratica compaiono tre stati:

StatoCosa significaSoluzione
Skipped loading symbolsIl caricamento dei simboli è filtrato dalle tue impostazioniControlla Debug > Options > Symbols per una regola di inclusione/esclusione che blocca questo modulo
Cannot find or open the PDB fileNessun .pdb corrispondente è raggiungibileCopia sulla macchina remota il .pdb esatto della build che ha prodotto il binario distribuito, oppure punta Visual Studio verso di esso
Nessuna voce / solo hex tipo nativoIl modulo non ha alcuna informazione di debugÈ stato compilato in Release senza .pdb, oppure è una DLL di sistema che non devi debuggare

Gran parte del tempo perso qui viene da una sola regola: il debugger accetta solo un .pdb che combacia esattamente con il binario. Non “la stessa versione”: il file di quella specifica build. Se la macchina remota è stata ridistribuita dopo la tua ultima build locale, il tuo .pdb locale non combacia più. Quando il caricamento automatico non lo trova, fai clic destro sul modulo nella finestra Modules, scegli Load Symbols e naviga fino alla cartella di output di quel deploy.

L’abitudine che previene tutto questo: distribuisci il .pdb insieme al binario a ogni deploy che potresti dover debuggare. Ricostruirne uno corrispondente dopo il fatto raramente funziona.

Come debuggare un processo in un container Docker

Tutto quello visto finora presuppone una macchina Windows su cui puoi installare software. Un container è diverso. Non metti msvsmon in un’immagine di produzione, e a seconda della configurazione della rete Docker, il container potrebbe non essere nemmeno raggiungibile per nome dal tuo host.

Se il progetto ha il supporto Docker attivo (Add > Docker Support, o un progetto già scaffoldato con un Dockerfile), ci pensa il tooling per container di Visual Studio: F5 compila un’immagine configurata per il debug, avvia il container e si aggancia. Per un container che non hai avviato da Visual Studio, apri Debug > Attach to Process, imposta Connection type su Docker (Linux Container) o Docker (Windows Container) a seconda dell’immagine, e scegli il container dalla lista. Visual Studio passa attraverso il demone Docker e mette il proprio debugger dentro il container in esecuzione, quindi non devi mai aggiungerne uno tu stesso all’immagine.

Come debuggare da remoto un’app su Azure App Service

Per un’app distribuita su Azure App Service, salta la configurazione manuale del debugger remoto. Clic destro sul progetto in Solution Explorer, scegli Publish, poi dal menu … del profilo di pubblicazione seleziona Attach Debugger. Visual Studio abilita l’endpoint di debug remoto sull’istanza App Service e gestisce la connessione e l’autenticazione al posto tuo. Una volta agganciato, le regole sui simboli viste sopra valgono comunque. Controlla la finestra Modules prima di fidarti di un breakpoint.

Debugger remoto o git bisect: quale usare per primo

Un debugger remoto ti dice cosa sta facendo adesso una riga specifica, su una macchina specifica. Non può dirti quale commit ha introdotto il problema. git bisect risponde proprio a quello, con una ricerca binaria sulla storia invece che una ricerca nella tua memoria.

Per una regressione, seguili in quest’ordine. Se non sai ancora quale commit ha rotto le cose, fai prima bisect. Una volta che hai il commit e una macchina dove il bug si riproduce, configura lì il debugger remoto e scopri perché.

Articoli correlati