Déboguer un bug qui n’apparaît que sur une machine sans Visual Studio
Un bug se reproduit sur le serveur de test et pas sur votre ordinateur portable. Le serveur de test n’a pas Visual Studio, et installer un IDE complet dessus pour poser un seul breakpoint n’est pas envisageable. Le débogage à distance est fait pour ce cas. Un petit programme autonome tourne sur la machine cible, votre Visual Studio local s’y connecte par le réseau, et vous obtenez des breakpoints et l’inspection de variables sur un process qui ne tourne nulle part près de votre bureau.
Il y a trois étapes : lancer le remote debugger sur la cible, s’y attacher depuis Visual Studio, charger les bons symboles. Chacune échoue d’une façon qui lui est propre. Viennent ensuite les deux cibles distantes que vous rencontrerez le plus souvent en pratique : un process dans un conteneur Docker et une app sur Azure App Service.
Comment installer et lancer le remote debugger de Visual Studio (msvsmon)
Le programme s’appelle msvsmon.exe, le Visual Studio Remote Debugger. Vous pouvez l’installer sur la machine cible de deux façons.
Si la cible a déjà Visual Studio Community, Professional ou Enterprise installé, msvsmon.exe s’y trouve déjà, sous <dossier d'installation Visual Studio>\Common7\IDE\Remote Debugger\x64\ (ou x86\, selon l’architecture que vous déboguez). Lancez-le directement.
Sinon, téléchargez le paquet d’outils distants autonome depuis la page des outils distants de Microsoft pour votre version de Visual Studio, et prenez sa dernière mise à jour. La compatibilité ne fonctionne que dans un sens : des outils distants plus récents marchent avec un Visual Studio plus ancien, mais des outils distants plus anciens peuvent refuser un Visual Studio plus récent. Choisissez l’architecture du système d’exploitation cible (x86, x64 ou ARM64), pas celle de l’app que vous déboguez.
Le premier lancement ouvre un assistant de configuration qui ajoute une règle au pare-feu Windows pour le type de réseau sur lequel vous êtes (domaine, privé ou public). Une fois terminé, la fenêtre du Remote Debugger affiche un nom de serveur et un port. C’est l’adresse que vous saisirez dans Visual Studio. Laissez la fenêtre ouverte ; la fermer (File > Exit) termine la session.
Ports et authentification du remote debugger : ce qui bloque la connexion
La règle de pare-feu créée par l’assistant n’ouvre que le port TCP entrant, et ce port change selon la version de Visual Studio. C’est 4026 pour Visual Studio 2022 ; les versions plus anciennes utilisent d’autres numéros. Si la cible se trouve derrière un pare-feu que l’assistant n’a pas configuré, comme une appliance d’entreprise ou un security group cloud, ouvrez ce port précis vous-même. Deviner « le port du debugger » sans vérifier votre version fait perdre du temps.
L’UDP 3702 sortant est optionnel. Il permet à la cible d’apparaître dans le sélecteur Find de Visual Studio. Sans lui, vous pouvez toujours vous connecter ; vous saisissez l’adresse à la main.
Le mode d’authentification doit correspondre des deux côtés. Par défaut, le remote debugger utilise l’authentification Windows, donc le compte Windows qui fait tourner Visual Studio a besoin d’une autorisation sur le remote debugger. Accordez-la depuis Tools > Permissions dans la fenêtre du Remote Debugger (droits administrateur requis), ou démarrez msvsmon en ligne de commande avec le compte déjà autorisé :
| |
Basculer sur No Authentication (Tools > Options dans la fenêtre du Remote Debugger) évite tout cela, et sur une VM jetable, c’est tentant. Ne le faites que sur un réseau auquel vous faites entièrement confiance. Quiconque peut atteindre ce port peut s’attacher à n’importe quel process tournant sous le même compte : aucun prompt, aucun mot de passe.
Comment s’attacher à un process distant depuis Visual Studio
Avec le remote debugger lancé et joignable :
- Dans Visual Studio, ouvrez Debug > Attach to Process (
Ctrl+Alt+P). - Réglez Connection type sur Remote (Windows).
- Dans Connection target, saisissez l’adresse au format affiché par la fenêtre du remote debugger elle-même, généralement
<nom-machine>:<port>. Si le nom de machine ne se résout pas, utilisez l’IP :10.0.0.15:4026. - Cliquez sur Refresh pour récupérer la liste des process depuis la machine distante, puis trouvez et sélectionnez votre process. S’il ne tourne pas sous votre compte, cochez Show processes from all users. Visual Studio affiche un avertissement de sécurité avant de vous attacher à un process appartenant à quelqu’un d’autre ; lisez-le plutôt que de le fermer.
- Laissez Code type sur Automatic. L’exception est un process au code mixte où l’attachement échoue silencieusement pour un langage : choisissez ce langage explicitement et rattachez-vous, vous obtiendrez une erreur précise au lieu de rien.
- Cliquez sur Attach.
Pour une app ASP.NET hébergée sur IIS, le process recherché est w3wp.exe. Pour une app .NET qui fait tourner son propre serveur Kestrel, c’est dotnet.exe ou le nom de l’exécutable de l’app. IIS fait souvent tourner plusieurs w3wp.exe identiques côte à côte. La colonne Command Line dans la liste des process est ce qui permet de les distinguer.
Résoudre « aucun symbole chargé » en débogage à distance
S’attacher ne veut pas dire que vous pouvez déjà déboguer. Ouvrez Debug > Windows > Modules et regardez la colonne Symbol Status pour votre binaire. Un cercle de breakpoint rouge creux au lieu d’un plein dit la même chose côté éditeur : le debugger n’a aucun symbole pour faire correspondre ce breakpoint.
Trois statuts reviennent en pratique :
| Statut | Ce que ça signifie | Correction |
|---|---|---|
Skipped loading symbols | Le chargement des symboles est filtré par vos réglages | Vérifiez Debug > Options > Symbols pour une règle d’inclusion/exclusion qui bloque ce module |
Cannot find or open the PDB file | Aucun .pdb correspondant n’est joignable | Copiez le .pdb exact du build qui a produit le binaire déployé vers la machine distante, ou pointez Visual Studio dessus |
| Aucune entrée / uniquement de l’hexadécimal natif | Le module n’a aucune info de debug | Il a été construit en Release sans .pdb, ou c’est une DLL système que vous n’avez pas besoin de déboguer |
L’essentiel du temps perdu ici vient d’une seule règle : le debugger n’accepte qu’un .pdb qui correspond exactement au binaire. Pas « la même version ». Le fichier de ce build précis. Si la machine distante a été redéployée depuis votre dernier build local, votre .pdb local ne correspond plus. Quand le chargement automatique ne le trouve pas, faites un clic droit sur le module dans la fenêtre Modules, choisissez Load Symbols, et naviguez jusqu’au propre dossier de sortie du déploiement.
L’habitude qui évite tout cela : livrez le .pdb avec le binaire à chaque déploiement que vous pourriez avoir besoin de déboguer. Reconstruire un .pdb correspondant après coup fonctionne rarement.
Comment déboguer un process dans un conteneur Docker
Tout ce qui précède suppose une machine Windows sur laquelle vous pouvez installer des logiciels. Un conteneur, c’est différent. Vous ne mettez pas msvsmon dans une image de production, et selon la configuration du réseau Docker, le conteneur n’est peut-être même pas joignable depuis votre hôte par son nom.
Si le projet a le support Docker activé (Add > Docker Support, ou un projet déjà généré avec un Dockerfile), l’outillage conteneur de Visual Studio fait le travail : F5 construit une image configurée pour le debug, démarre le conteneur, et s’y attache. Pour un conteneur que vous n’avez pas lancé depuis Visual Studio, ouvrez Debug > Attach to Process, réglez Connection type sur Docker (Linux Container) ou Docker (Windows Container) selon l’image, et choisissez le conteneur dans la liste. Visual Studio passe par le daemon Docker et place son propre debugger dans le conteneur en cours d’exécution, vous n’en ajoutez donc jamais un vous-même dans l’image.
Comment déboguer à distance une app sur Azure App Service
Pour une app déployée sur Azure App Service, sautez la configuration manuelle du remote debugger. Faites un clic droit sur le projet dans Solution Explorer, choisissez Publish, puis dans le menu … du profil de publication, sélectionnez Attach Debugger. Visual Studio active l’endpoint de débogage à distance sur l’instance App Service et gère la connexion et l’authentification pour vous. Une fois attaché, les règles de symboles des sections précédentes s’appliquent toujours. Vérifiez la fenêtre Modules avant de faire confiance à un breakpoint.
Remote debugger ou git bisect : lequel utiliser en premier
Un remote debugger vous dit ce qu’une ligne précise fait en ce moment, sur une machine précise. Il ne peut pas vous dire quel commit a introduit le problème. git bisect répond à cette question-là, avec une recherche binaire dans l’historique plutôt qu’une recherche dans votre mémoire.
Pour une régression, utilisez-les dans cet ordre. Si vous ne savez pas encore quel commit a cassé les choses, faites d’abord un bisect. Une fois que vous avez le commit et une machine où le bug se reproduit, montez le remote debugger là-bas et trouvez pourquoi.