Process Explorer / Handle / VMMap en pratique — Diagnostiquer les blocages, fuites et « fichiers en cours d'utilisation » à partir de l'état du système à cet instant précis
· Go Komura · Sysinternals, Process Explorer, VMMap, Fuite de handles, Fuite de mémoire, Diagnostic de panne, Windows, Fonctionnement longue durée
« Il suffit de redémarrer le lundi matin pour que ça se remette à fonctionner » — c’est une phrase que nous avons entendue à de nombreuses reprises lors de consultations sur la maintenance d’applications liées à des équipements. Tout fonctionne bien juste après le démarrage, mais vers le jeudi, les changements d’écran commencent à traîner, et le vendredi soir, appuyer sur un bouton ne donne plus aucune réponse pendant plusieurs secondes. De temps en temps apparaît une erreur jamais vue auparavant, du type « handle invalide ». Puis, après un redémarrage, tout redevient normal comme si de rien n’était. Une fois qu’on en arrive là, l’exploitation se fige sur un « redémarrage hebdomadaire », et la cause profonde reste inconnue de tous pendant des années.
Pour ce type de symptôme, on a beau examiner les journaux, on n’arrive jamais à la cause. Ce qu’il faut, c’est observer directement, « à cet instant précis, ce que ce processus détient et en quelle quantité ». Dans notre précédent article, le « Guide pratique de Process Monitor (ProcMon) », nous avions traité ProcMon, qui enregistre la chronologie des opérations. Cette fois, en guise de suite — deuxième volet pratique de la série Sysinternals —, nous organisons les outils qui observent l’état du système — Process Explorer, Handle et VMMap — autour des trois grands symptômes des applications à fonctionnement longue durée : « ça ralentit progressivement », « impossible de supprimer un fichier » et « ça s’est bloqué ».
L’environnement de référence de cet article est le suivant.
- Système d’exploitation — La configuration officielle requise pour Process Explorer est Windows 11 ou ultérieur côté client, et Windows Server 2016 ou ultérieur côté serveur.1
- Architecture — Sur un environnement 64 bits, lancer
procexp.exedéploie et exécute automatiquement la version 64 bits. Pour voir correctement les piles et les handles des processus 64 bits, il faut fonctionner sous cette version 64 bits. - Privilèges — Pour un usage d’investigation, « Exécuter en tant qu’administrateur » est de fait indispensable. Avec des privilèges standard, la pile des threads comme la liste des handles renverront « Accès refusé » pour les processus appartenant à d’autres utilisateurs ou à des services. La version CLI
handle.exerequiert officiellement des privilèges administrateur.2 - Premier lancement — Une boîte de dialogue de consentement à l’EULA (contrat de licence d’utilisation) apparaît. Pour les scripts ou l’exécution sans surveillance, le commutateur
/accepteulapermet d’expliciter ce consentement (chapitre 8).
Notez que cet article traite de l’utilisation d’outils graphiques, mais qu’il ne comporte pas de captures d’écran. À la place, les noms de menus et les raccourcis clavier sont écrits tels qu’ils apparaissent réellement, de façon à pouvoir suivre l’article tout en ayant l’outil ouvert sous les yeux.
1. La conclusion, d’abord
- ProcMon montre « l’historique », Process Explorer montre le « présent ». Process Explorer est un outil qui permet de lister et de rechercher les handles ouverts et les DLL chargées par chaque processus ; la documentation officielle indique elle-même qu’il convient à l’investigation des problèmes de version de DLL et des fuites de handles.1
- Pour « impossible de supprimer ou de remplacer un fichier », Find Handle or DLL (Ctrl+F) est la voie la plus rapide. Une recherche sur une partie du chemin identifie en quelques secondes le processus qui détient ce fichier (chapitre 3).
- Pour « ça s’est bloqué », consultez la pile des threads via Propriétés du processus → onglet Threads. Mais sans configuration des symboles (dbghelp.dll et chemin des symboles), vous n’obtiendrez qu’une liste d’adresses (chapitre 4).13
- Pour « ça ralentit progressivement », ajoutez des colonnes et observez la tendance. Ajoutez les quatre colonnes Handle Count, USER Objects, GDI Objects et Private Bytes, puis recherchez, avec le temps, ce qui continue d’augmenter. Les objets GDI/USER ont une limite par processus ; une fois atteinte, le rendu graphique et la création de fenêtres commencent à se casser (chapitre 5).4
- La version CLI handle.exe convient à l’observation régulière par script.
handle -s -p <processus>permet d’enregistrer périodiquement le nombre de handles par type. La fermeture forcée d’un handle avec-cest déconseillée par la documentation officielle elle-même, qui avertit d’une possible instabilité ; on ne l’utilise fondamentalement pas.2 - Décomposez « Private Bytes ne cesse d’augmenter » avec VMMap. Si c’est Heap, le terrain est natif ; si c’est Managed Heap, le terrain est .NET : déterminez d’abord ce terrain avant de passer à l’outil dédié (chapitre 6).5
- Quand c’est la mémoire de l’OS dans son ensemble qui est suspecte, et non un processus en particulier, utilisez RAMMap.6 En cas de plantage, basculez vers la capture d’un dump avec ProcDump (« Introduction à la collecte de dumps de plantage Windows »).
- Aucun de ces outils ne nécessite d’installation, et tous peuvent aussi s’exécuter directement depuis Sysinternals Live. Ils sont donc faciles à apporter même sur un PC d’équipement hors ligne, mais seuls les symboles nécessitent une préparation préalable (chapitre 8).7
2. Les bases de Process Explorer — Exécution en administrateur, remplacement du Gestionnaire des tâches et lecture de l’écran
Process Explorer ne nécessite aucune installation : il suffit d’extraire le ZIP et d’exécuter procexp.exe (sur un système 64 bits, procexp64 se lance automatiquement).1 Comme cet outil permet de voir jusqu’à l’intérieur des processus d’autres utilisateurs ou de services, exécutez-le toujours « en tant qu’administrateur » lors d’une investigation. Lancé avec des privilèges standard, il renverra « Accès refusé » précisément pour les processus qui vous intéressent, sans afficher ni la pile ni les handles.
Sur les machines dédiées à l’investigation, activer Options → Replace Task Manager fait que tout appel au Gestionnaire des tâches, que ce soit via Ctrl+Shift+Échap ou depuis la barre des tâches, ouvre directement Process Explorer. L’effet discret mais réel d’avoir « toujours l’outil habituel qui s’ouvre au moment critique » est appréciable ; chez nous aussi, toutes les machines de développement sont configurées ainsi (le même menu permet de revenir en arrière).
L’écran se compose de deux volets : l’arborescence des processus en haut, et les détails du processus sélectionné en bas. Le volet inférieur bascule, via View → Lower Pane View, entre la vue Handles (liste des handles ouverts) et la vue DLLs (liste des DLL chargées et des fichiers mappés en mémoire).1 La première chose à retenir est la signification des couleurs de ligne (consultables et modifiables via Options → Configure Colors).
| Couleur (par défaut) | Signification |
|---|---|
| Vert | Processus nouvellement lancé (environ 1 seconde par défaut) |
| Rouge | Processus en cours de fin d’exécution |
| Bleu clair | Processus appartenant au même compte utilisateur que vous |
| Rose | Processus hébergeant un service |
| Violet | Exécutable suspecté d’être empaqueté (compressé/obfusqué) |
| Gris foncé | Processus suspendu |
Une anomalie comme « un processus naît en vert un bref instant, devient aussitôt rouge et disparaît », répétée indéfiniment, se repère uniquement grâce à l’arborescence et au code couleur. Comme les relations parent-enfant des processus sont visibles dans l’arborescence, on voit aussi d’un coup d’œil « de qui ce conhost.exe est-il l’enfant » ou « est-ce un service ou le Planificateur de tâches qui lance l’application ».
3. « Fichier en cours d’utilisation, impossible à supprimer » — Identifier le coupable avec Find Handle or DLL
« Impossible de supprimer un fichier journal », « l’exe est en cours d’utilisation lors d’une tentative de mise à jour », « impossible de retirer une clé USB en toute sécurité » — l’investigation de ce type de symptôme se termine avec Find → Find Handle or DLL (Ctrl+F).1 L’opération se déroule en 5 étapes.
- Exécutez Process Explorer en tant qu’administrateur (l’oublier signifie que rien ne s’affichera si le détenteur est un service ou le processus d’un autre utilisateur)
- Ouvrez le menu Find > Find Handle or DLL… (raccourci Ctrl+F)
- Dans le champ de recherche, saisissez une partie du nom de fichier ou de dossier (par exemple
report.csv,D:\Data). Le chemin complet n’est pas nécessaire : la recherche se fait par correspondance partielle - Cliquez sur Search. La liste affiche les processus qui ont ouvert un handle contenant ce nom, ou qui ont chargé cette DLL
- En cliquant sur une ligne du résultat, le processus correspondant est sélectionné dans le volet supérieur, et le handle correspondant est surligné dans le volet inférieur
Une fois le coupable trouvé, la bonne méthode consiste à « terminer proprement ce processus ». Il est possible de forcer la fermeture en faisant un clic droit sur le handle dans Process Explorer et en choisissant Close Handle, mais ce n’est pas recommandé en production, pour la même raison que handle -c mentionné plus loin.
Prenez aussi conscience dès maintenant de la limite de cette recherche : elle ne trouve que les objets nommés. Les événements, mutex ou handles de thread sans nom, même ouverts en très grand nombre, ne peuvent pas être trouvés par leur nom. Cette méthode est imbattable pour une investigation où existe un nom, comme un chemin, dans le cas de « fichier impossible à supprimer », mais elle est inutilisable pour l’investigation des fuites de handles du chapitre 5 : il faut alors basculer vers l’agrégation par type (handle -s) et le tri de la vue Handles du volet inférieur par colonne Type (l’étude de cas du chapitre 7 en est un exemple concret).
La vue DLLs sert aussi à vérifier « quelle version de quelle DLL, à quel emplacement, a réellement été chargée ». Pour confirmer un problème de version de DLL — « une ancienne DLL était toujours détenue », « le correctif censé être déployé n’a pas été chargé » — cet écran forme un binôme avec la section 5.2 de l’article ProcMon précédent, « Ça ne démarre que dans cet environnement-là — Suivre la recherche des DLL ». Cette section-là suit chronologiquement l’ordre de recherche, où s’alignent les NAME NOT FOUND jusqu’au SUCCESS (ou jusqu’à l’échec final), et révèle où l’application a cherché. Cette vue DLLs-ci révèle ce qui a finalement été chargé et d’où. Pour plus de détails, consultez le « Guide pratique de Process Monitor (ProcMon) ».
D’ailleurs, « comment remplacer en toute sécurité un exe/DLL en cours d’utilisation » est une question de conception, pas d’investigation. L’article compagnon publié le même jour, « Comment remplacer un exe/DLL en cours d’utilisation », traite de la conception du remplacement, Restart Manager compris ; si vous construisez un mécanisme de mise à jour, reportez-vous-y.
4. « Ça s’est bloqué » — Lire la pile des threads dans l’onglet Threads
La fenêtre devient blanche et ne répond plus. Avant de forcer la fermeture, consultez la pile des threads dans l’onglet Threads. L’opération se déroule en 4 étapes.
- Double-cliquez sur le processus concerné dans le volet supérieur (ou clic droit → Properties…). La fenêtre des propriétés s’ouvre
- Basculez vers l’onglet Threads. L’utilisation CPU, le nombre de cycles et l’adresse de départ de chaque thread s’affichent
- Choisissez le thread à examiner. Le thread qui consomme continuellement du CPU, ou celui dont l’adresse de départ pointe vers l’EXE principal de l’application (dans la plupart des cas, le thread d’interface utilisateur), sont les premiers candidats
- Cliquez sur le bouton Stack. Il affiche, de l’appel le plus récent vers le plus ancien, dans quel appel de fonction ce thread est actuellement bloqué
La plupart des blocages proviennent du fait que « le thread d’interface utilisateur attend quelque chose » : si vous voyez WaitForSingleObject, EnterCriticalSection, ou une attente synchrone d’E/S réseau ou série en haut de la pile, c’est la cause directe.
Cependant, sans configuration des symboles, la pile ne montre qu’une liste d’adresses et de nom_module+0x1234, quasiment illisible. Configurez les deux éléments suivants via Options → Configure Symbols.
Dbghelp.dll path:
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\dbghelp.dll
* Indiquer celui fourni avec WinDbg (Debugging Tools for Windows)
Symbols path:
srv*C:\Symbols*https://msdl.microsoft.com/download/symbols
* C:\Symbols est le cache local. Dès la deuxième fois, la lecture s'y fait
Deux points sont essentiels. Premièrement, le dbghelp.dll par défaut présent dans System32 ne prend pas en charge le téléchargement depuis un serveur de symboles : il faut pointer vers celui fourni avec WinDbg. Deuxièmement, comme l’indique la documentation officielle, si vous utilisez un serveur de symboles, symsrv.dll doit se trouver au même emplacement que le dbghelp.dll indiqué (le dossier d’installation de WinDbg contient les deux).1 Le format srv*cache*URL_serveur du chemin des symboles, ainsi que le serveur public de symboles Microsoft https://msdl.microsoft.com/download/symbols, sont le même mécanisme que celui utilisé par WinDbg.3 Pour lire la pile de vos propres applications, il faut aussi les PDB de vos propres builds : ajoutez donc au chemin des symboles, séparé par un point-virgule, le dossier où sont stockés ces PDB.
D’où récupérer ce dbghelp.dll est le premier point de blocage. Le chemin C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ mentionné ci-dessus est un dossier créé par l’installation de Debugging Tools for Windows. Il existe trois façons de l’obtenir.8
| Méthode d’obtention | Cas d’usage adapté |
|---|---|
| Ne cocher que « Debugging Tools for Windows » dans l’installeur du Windows SDK | La voie la plus rapide pour cet usage. En décochant toutes les autres fonctionnalités, seul le débogueur s’installe, sans le SDK lui-même8 |
| L’installer dans le cadre du Windows SDK / WDK | Quand la machine de développement a aussi besoin du SDK pour d’autres usages |
Installer WinDbg seul (winget install Microsoft.WinDbg ou le Microsoft Store) |
Quand vous voulez utiliser WinDbg lui-même. Comme il s’installe sous forme de paquet, le chemin n’est cependant pas fixe comme ci-dessus9 |
Ce que vous configurez dans Process Explorer est le chemin du fichier dbghelp.dll : après l’installation, vérifiez que dbghelp.dll et symsrv.dll se trouvent bien côte à côte dans ce dossier avant de le renseigner.
Pour une application .NET, la pile de l’onglet Threads est centrée sur les frames natifs, et les noms de méthodes managées peuvent ne pas s’afficher correctement. Pour traquer sérieusement un blocage ou un interblocage managé, il est plus fiable de capturer un dump pendant le blocage et de l’examiner avec WinDbg + SOS (« Lire un dump de plantage avec WinDbg + SOS »). La répartition des rôles est la suivante : l’onglet Threads sert à « se faire une idée sur place en trois minutes », le dump sert à « confirmer une fois ramené ». Notez que les boutons Kill/Suspend de l’onglet Threads ne doivent jamais être pressés sur un processus de production : ce qui devait être une observation devient une intervention.
5. « Ça ralentit progressivement » — Surveiller les fuites avec le nombre de handles, les colonnes USER/GDI et handle.exe
La cause classique de dégradation d’une application à fonctionnement longue durée réside dans les fuites de handles, d’objets GDI/USER et de mémoire. Process Explorer est aussi un excellent outil de surveillance : ajoutez les colonnes suivantes via View → Select Columns.
- Onglet Process Performance → Handle Count (nombre de handles d’objets noyau)
- Onglet Process Memory → Private Bytes, Virtual Size, USER Objects, GDI Objects
Ce qu’il faut observer n’est pas la valeur absolue mais la tendance. Dans une application saine, le nombre de handles monte et descend au gré des opérations tout en restant dans une plage stable ; en cas de fuite, il grimpe « à chaque opération, sans jamais redescendre ». Même de simples captures d’écran toutes les heures, ou matin et soir, suffisent à révéler la tendance dès le lendemain. Les objets GDI et USER ont une limite par processus (10 000 par défaut, modifiable via le registre avec GDIProcessHandleQuota entre autres) et une limite théorique de session de 65 536 au total ; une fois cette limite atteinte, la création de stylos, de brosses ou de fenêtres commence à échouer.4 « L’affichage se met à déraper le vendredi » a le plus souvent cette cause.
Pour un environnement sans interface graphique ou une observation régulière par script, utilisez la version CLI handle.exe. C’est un outil en ligne de commande de listage et de recherche de handles, qui requiert des privilèges administrateur.2
:: Qui retient ce fichier/dossier (recherche par correspondance partielle du nom)
handle.exe /accepteula report.csv
handle.exe D:\Data
:: Dump de tous les types de handles, fichiers compris, en filtrant par nom de processus
handle.exe -a -p MyEquipApp
:: Agréger le nombre de handles par type ── à consigner dans un journal pour l'observation régulière des fuites
handle.exe -s -p MyEquipApp.exe >> C:\Logs\handles_%date:~0,4%%date:~5,2%%date:~8,2%.log
Une précision sur %date:~0,4% à la troisième ligne. Il s’agit d’un découpage en sous-chaîne d’une variable d’environnement : que ce soit dans un fichier batch ou tapé directement dans l’invite de commandes, l’écriture est identique, avec un seul % (le doublement en %% n’est nécessaire que pour les variables de for ou pour écrire un % littéral ; cette notation-ci n’en fait pas partie).
Cependant, le contenu de %date% dépend du format de date court de l’OS, si bien qu’un décalage comme ~0,4 (les 4 premiers caractères = l’année) varie selon l’environnement. Le format par défaut sur la version japonaise de Windows est yyyy/MM/dd, ce qui correspond à l’exemple ci-dessus, mais si les paramètres régionaux du PC d’équipement diffèrent, le nom de fichier sera généré de façon incorrecte. Pour un script d’observation régulière distribué sur plusieurs environnements, faites en sorte que seule la génération de la date utilise une méthode au format garanti.
:: Écriture indépendante du format de date de l'environnement (dans un fichier batch)
for /f %%d in ('powershell -NoProfile -Command "Get-Date -Format yyyyMMdd"') do set TODAY=%%d
handle.exe -s -p MyEquipApp.exe >> C:\Logs\handles_%TODAY%.log
Les variables de for doivent s’écrire différemment : %%d dans un fichier batch, %d lorsqu’elles sont tapées directement dans l’invite de commandes.10 Le code ci-dessus est destiné à un fichier batch ; le coller tel quel dans l’invite de commandes ne fonctionnera pas. Pour un essai direct, remplacez %%d par %d. Comme l’observation régulière est destinée à être exécutée depuis le Planificateur de tâches, l’usage réel utilise l’écriture pour fichier batch. C’est le point qu’on confond facilement avec %date:~0,4% mentionné plus haut (un seul % dans les deux cas).
En ajoutant la sortie de -s (l’agrégation par type, du genre Event: 1523, File: 88, …) toutes les heures via le Planificateur de tâches, même un PC d’équipement accessible uniquement en maintenance à distance permet d’obtenir des chiffres sur « combien de handles de quel type augmentent chaque jour ». Une fois le type connu, les suspects se réduisent immédiatement : Event évoque un oubli de libération d’événement, File un oubli de fermeture, Thread des handles laissés après la fin d’un thread, et ainsi de suite.
Notez que l’option -c permet de forcer la fermeture d’un handle donné, mais la documentation officielle elle-même avertit que « fermer un handle peut déstabiliser l’application ou le système ».2 Même comme remède d’urgence pour débloquer un verrou, notre politique consiste fondamentalement à ne pas l’utiliser en production. Une fois que l’on sait « quel type fuit », la procédure pour identifier « quel code l’a alloué » se poursuit dans « Investigation d’un plantage longue durée sur une caméra industrielle - Épisode fuite de handles » et « Poser les bases de tests anormaux avec Application Verifier ».
6. VMMap — Décomposer « Private Bytes ne cesse d’augmenter »
Les handles restent stables mais seul Private Bytes continue d’augmenter — c’est là qu’on ouvre VMMap. C’est un outil d’analyse de la mémoire virtuelle et physique (working set) d’un processus, qui décompose par type la mémoire virtuelle validée (committed).5 Au lancement, une fois le processus cible sélectionné, un résumé codé par couleur apparaît en haut, et une carte mémoire détaillée en bas. Voici comment lire les principales catégories.
| Catégorie | Contenu | Coupable typique en cas d’augmentation continue |
|---|---|---|
| Image | Le corps de l’EXE/DLL | DLL de plugin jamais déchargée |
| Heap | Tas natif (new/malloc/HeapAlloc) | Fuite de libération dans du code C/C++, un SDK d’équipement, ou de l’interopérabilité |
| Managed Heap | Tas GC .NET | Fuite de référence managée (gestionnaire d’événements, etc.) |
| Private Data | Allocation directe via VirtualAlloc, etc. | Tampon de trame d’image, tampon interne d’un SDK |
| Stack | Pile des threads | Threads créés sans jamais être arrêtés |
| Shareable / Mapped File | Mémoire partagée, fichiers mappés | Fuite de libération de section pour la communication inter-processus |
L’opération se déroule en 4 étapes.
- Exécutez VMMap en tant qu’administrateur. Une boîte de dialogue de sélection de processus apparaît immédiatement au lancement ; sélectionnez le processus cible et cliquez sur OK
- Consultez le tableau récapitulatif en haut. Les lignes correspondent au Type du tableau ci-dessus (Image / Heap / Managed Heap / Private Data / Stack…), les colonnes à des tailles comme Size ou Committed. Il est essentiel de noter les valeurs à ce stade, ou de les exporter via le menu File
- Répétez l’opération problématique (un cycle de mesure de l’équipement, l’ouverture/fermeture d’un écran, etc.) un nombre de fois fixe
- Actualisez l’instantané avec F5 (Refresh) et comparez avec les valeurs notées à l’étape 2. Cliquer sur la ligne du Type qui a augmenté affiche la liste de ces régions en bas
Le schéma d’utilisation est le suivant : « actualiser l’instantané avec F5 tout en répétant l’opération problématique, et observer quelle catégorie augmente ». Comme VMMap prend en charge la comparaison d’instantanés, l’affichage en chronologie et l’export des résultats5, on peut obtenir sur le champ une preuve du type « après 100 mesures, Heap a augmenté de 40 Mo, Managed Heap est resté stable ». Une fois le terrain déterminé, place aux outils dédiés : pour Managed Heap, l’investigation côté .NET (« Identifier ce qui est « lent » avec PerfView et dotnet-trace ») ; pour Heap/Private Data, l’investigation côté natif (Application Verifier ou analyse de dump). Suspecter directement le GC sans faire cette distinction, et y perdre plusieurs jours, est le détour le plus courant pour les applications d’équipement combinant .NET et SDK natif.
Pour un processus 32 bits, la fragmentation est aussi à observer. La vue Fragmentation View visualise la dispersion de l’espace libre dans l’espace d’adressage, révélant des situations où le total Free s’élève à plusieurs centaines de Mo alors que le plus grand bloc contigu libre (Largest) ne fait que quelques dizaines de Mo. « OutOfMemory alors que la mémoire devrait être disponible », « seule l’allocation d’un grand tampon d’image échoue » ont le plus souvent cette cause, et cela sert de justification pour des contre-mesures comme le passage en 64 bits ou une conception de réutilisation des tampons.
Quand c’est la mémoire de l’OS dans son ensemble qui est suspecte plutôt qu’un processus en particulier (manque de mémoire alors qu’aucun processus n’est particulièrement gros), basculez vers RAMMap, qui affiche par onglet l’usage de la totalité de la mémoire physique. Comme il montre même l’utilisation par le cache de fichiers, les pilotes et le noyau, c’est l’outil pour chercher « un coupable en dehors de l’application ».6
7. Étude de cas — Diagnostiquer « le PC d’équipement qui ralentit chaque vendredi »
Voici comment le PC d’équipement mentionné en introduction se diagnostique réellement avec les outils vus jusqu’ici. Comme l’exploitation redémarre le lundi matin, le vendredi correspond au « 5ᵉ jour de fonctionnement ». L’hypothèse initiale est donc qu’il existe quelque chose qui augmente proportionnellement au temps.
- Placer Process Explorer vers le mercredi et préparer les colonnes. Ajoutez Handle Count, USER Objects, GDI Objects et Private Bytes, et notez les valeurs du processus cible. Enregistrez en parallèle une journalisation horaire de
handle -s -p appli_cible.exedans le Planificateur de tâches (chapitre 5). - Le lendemain, observer la tendance. Dans ce cas, Handle Count a augmenté d’environ 20 000 en une journée, et le journal par type montrait une augmentation monotone des handles Event. Private Bytes et GDI/USER étaient à peu près stables. On peut, à ce stade, se limiter à une « fuite de libération d’un objet noyau (événement) ».
- Observer la réalité dans la vue Handles. En triant la vue Handles du volet inférieur par colonne Type, on trouve des dizaines de milliers d’Event sans nom. Comme ils n’ont pas de nom, Find Handle ne peut pas les suivre, mais connaître le type et le rythme d’augmentation suffit. En le rapprochant du cycle de mesure (dans ce cas, 2 par cycle de scrutation de l’équipement), l’hypothèse d’une fuite de libération des événements d’attente d’une bibliothèque de communication s’est dégagée, et a été confirmée par revue de code. Pour identifier le point d’allocation à l’aide d’un outil, c’est ici qu’interviennent Application Verifier ou
!htrace. - Si Private Bytes avait augmenté, au lieu de l’étape 3, décomposez avec VMMap (chapitre 6), et orientez l’investigation vers le natif si c’est Heap, vers .NET si c’est Managed Heap.
- Si tous les chiffres restent stables et que seul un blocage survient, consultez la pile via l’onglet Threads (chapitre 4) pour identifier ce qui est attendu.
Le point essentiel est de s’assurer, avant la correction, d’une preuve sous forme de « pente du graphique ». En refaisant la même mesure après correction et en montrant que la pente est tombée à zéro, on peut rapporter « c’est corrigé » avec des chiffres. Pour un problème de fonctionnement longue durée dont la reproduction se compte en jours, cette mise en place de la mesure constitue le cœur même de l’investigation.
8. Déploiement sur un PC de production et précautions d’exploitation — Sysinternals Live, EULA et symboles hors ligne
Les outils Sysinternals sont tous des exécutables autonomes ne nécessitant aucune installation ; il suffit d’apporter le ZIP sur une clé USB pour qu’ils fonctionnent tels quels. Une boîte de dialogue de consentement à l’EULA apparaît au premier lancement ; pour une exécution sans surveillance ou un script, le commutateur /accepteula permet d’expliciter ce consentement. Dans un environnement disposant du réseau, le service Sysinternals Live permet de les exécuter directement, sans les télécharger, depuis une URL comme https://live.sysinternals.com/procexp.exe, ou depuis le chemin UNC \\live.sysinternals.com\tools\<nom_outil>.7 C’est la voie la plus rapide quand on veut « regarder tout de suite, sur cette seule machine ».
Ce qui pose problème sur un PC d’équipement hors ligne, ce sont les symboles (l’affichage de la pile du chapitre 4 devient inutilisable). Il y a deux solutions : (1) résoudre les symboles sur une machine de développement connectée à Internet, pour la même version d’OS, puis copier tout le cache local (C:\Symbols) sur le PC d’équipement en configurant le chemin des symboles pour qu’il ne pointe que vers ce dossier local ; (2) renoncer à l’analyse de la pile, se limiter sur place à la capture d’un dump (ProcDump) et à la consignation de chiffres, puis ramener le tout sur la machine de développement pour l’analyse. La solution (2) est la plus fiable ; la façon de capturer un dump est décrite dans « Introduction à la collecte de dumps de plantage Windows ».
Un dernier mot sur l’exploitation. L’observation via Process Explorer ou VMMap représente une faible charge et un faible risque, mais les opérations d’intervention — Kill/Suspend d’un processus, Kill d’un thread, Close Handle, handle -c — doivent en principe être interdites en production. Comme pour ProcMon dans l’article précédent, il est plus sûr de faire passer leur mise en œuvre par le même processus d’approbation qu’un changement ordinaire, en décidant à l’avance « qui observe quoi, quand, et ce qui ne doit pas être manipulé ».
9. Règles pratiques (tableau de décision)
| Symptôme | Outil à utiliser | Où regarder |
|---|---|---|
| Ça ralentit progressivement, devient instable en quelques jours | Process Explorer | Tendance des colonnes Handle Count / USER/GDI Objects / Private Bytes (chapitre 5) |
| Impossible de supprimer ou de remplacer un fichier | Process Explorer / handle.exe | Recherche de chemin avec Find Handle or DLL (Ctrl+F) → processus détenteur (chapitre 3) |
| Blocage, absence de réponse | Process Explorer | Propriétés → onglet Threads → pile des threads (symboles requis, chapitre 4) |
| Private Bytes ne cesse d’augmenter | VMMap | Quelle part augmente entre Heap / Managed Heap / Private Data (chapitre 6) |
| Manque de mémoire alors qu’aucun processus n’est particulièrement gros | RAMMap | Usage de la mémoire physique via Use Counts et File Summary6 |
| Plantage, arrêt sur exception | ProcDump + WinDbg | Collecte de dumps → WinDbg + SOS |
| Où le CPU est consommé, GC .NET | PerfView / dotnet-trace | Investigation quantitative de la « lenteur » |
| Chronologie des opérations (quel fichier, quand, dans quel ordre) | Process Monitor | Article précédent |
10. Conclusion
- Alors que ProcMon enregistre « l’historique des opérations », Process Explorer / Handle / VMMap sont des outils qui observent « l’état à cet instant précis ». L’investigation d’une application à fonctionnement longue durée nécessite les deux.
- « Impossible de supprimer un fichier » se résout en quelques secondes avec Find Handle or DLL (Ctrl+F), « ça s’est bloqué » se cerne avec la pile de l’onglet Threads. Lire la pile suppose au préalable dbghelp.dll (à l’emplacement où symsrv.dll est également présent) et un chemin de symboles configurés ; ce dbghelp.dll s’obtient en installant Debugging Tools for Windows.
- Seuls les objets nommés peuvent être trouvés par une recherche par nom. C’est imbattable pour un élément nommé comme un fichier, mais les événements ou mutex sans nom ne ressortiront jamais d’une recherche. Commencer une investigation de fuite de handles par « chercher le coupable avec Ctrl+F » fera chou blanc : basculez vers l’agrégation par type (
handle -s) et le tri de la vue Handles par colonne Type. - « Ça ralentit progressivement » se diagnostique en ajoutant les colonnes Handle Count, USER/GDI Objects et Private Bytes pour en observer la tendance. Une journalisation régulière de
handle -spermet d’obtenir des chiffres même sur un PC d’équipement où l’interface graphique n’est pas accessible. - L’augmentation de Private Bytes se décompose avec VMMap entre Heap (natif), Managed Heap (.NET) et Private Data, avant de passer à l’outil dédié. Pour un processus 32 bits, soupçonnez aussi la fragmentation.
- La fermeture forcée via
handle -cou Close Handle est, comme la documentation officielle le prévient, une source d’instabilité. En production, contentez-vous d’observer ; n’intervenez pas, ou si vous devez le faire, passez systématiquement par une approbation. - Ces outils sont autonomes et faciles à apporter, et Sysinternals Live permet même de les exécuter directement. Dans un environnement hors ligne, compensez avec une mise en cache préalable des symboles ou en ramenant un dump.
Articles connexes
- Guide pratique de Process Monitor (ProcMon) — Identifier en 10 minutes « la configuration n’est pas lue » ou « ACCESS DENIED »
- Comment remplacer un exe/DLL en cours d’utilisation
- Investigation d’un plantage longue durée sur une caméra industrielle - Épisode fuite de handles
- Poser les bases de tests anormaux avec Application Verifier
- Introduction à la collecte de dumps de plantage Windows - WER/ProcDump/WinDbg
- Lire un dump de plantage avec WinDbg + SOS
- Identifier ce qui est « lent » avec PerfView et dotnet-trace
Domaines de conseil associés
合同会社小村ソフト (Komura Software LLC) prend en charge l’investigation des fuites dans les applications métier et les applications liées à des équipements qui se dégradent en fonctionnement longue durée, l’analyse des causes des incidents de terrain comme les blocages ou les « fichiers en cours d’utilisation », ainsi que la mise en place des procédures de collecte de preuves et les corrections de prévention de la récurrence.
- Investigation de dysfonctionnements et analyse des causes
- Conseil technique et revue de conception
- Modification et maintenance de logiciels Windows existants
- Contact
Références
-
Microsoft Learn, Process Explorer - Sysinternals. Sur le fait que Process Explorer affiche, dans deux volets (mode handle / mode DLL), les handles ouverts et les DLL/fichiers mappés en mémoire chargés par un processus ; qu’il permet de rechercher les processus détenant un handle ou une DLL donnés ; qu’il est utile pour suivre les problèmes de version de DLL et les fuites de handles ; qu’en cas d’utilisation d’un serveur de symboles, symsrv.dll doit se trouver au même emplacement que dbghelp.dll ; qu’il peut s’exécuter directement depuis Sysinternals Live ; et que la configuration requise est Windows 11 ou ultérieur côté client, Windows Server 2016 ou ultérieur côté serveur. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Microsoft Learn, Handle - Sysinternals. Sur le fait que handle.exe est un outil en ligne de commande affichant des informations sur les handles ouverts et nécessitant des privilèges administrateur, sur la recherche par correspondance partielle de nom, sur
-apour cibler tous les types de handles, sur-ppour filtrer par processus, sur-spour agréger le nombre de handles par type, et sur le fait que-cpermet de fermer un handle mais qu’il est averti que cela « peut déstabiliser l’application ou le système ». ↩ ↩2 ↩3 ↩4 -
Microsoft Learn, Microsoft Public Symbol Server. Sur le fait que le chemin des symboles du serveur de symboles public Microsoft peut être indiqué au format srvcache_localehttps://msdl.microsoft.com/download/symbols, et que le magasin en aval (le cache local) ne conserve que les symboles déjà consultés une fois, les accès suivants étant lus localement. ↩ ↩2
-
Microsoft Learn, GDI Objects. Sur le fait que les handles GDI ont une limite théorique de 65 536 par session, et qu’il existe une limite par défaut par processus, modifiable via le registre GDIProcessHandleQuota (dans une plage de 256 à 65 536). ↩ ↩2
-
Microsoft Learn, VMMap - Sysinternals. Sur le fait que VMMap est un outil d’analyse de la mémoire virtuelle et physique d’un processus, qu’il affiche la répartition par type de la mémoire virtuelle validée ainsi que la mémoire physique (working set) allouée à chaque type, qu’il prend en charge les filtres et l’actualisation (instantanés), et qu’il permet l’export des données et le scriptage via des options en ligne de commande. ↩ ↩2 ↩3
-
Microsoft Learn, RAMMap - Sysinternals. Sur le fait que RAMMap est un outil d’analyse de l’utilisation de la mémoire physique à l’échelle de l’OS, qu’il affiche l’usage via des onglets tels que Use Counts (agrégation par type), Processes (working set des processus) et File Summary (données de fichiers en RAM), et qu’il prend en charge l’enregistrement et le chargement d’instantanés. ↩ ↩2 ↩3
-
Microsoft Learn, Sysinternals. Sur le fait que Sysinternals Live est un service permettant d’exécuter les outils sans les télécharger, qu’ils peuvent s’exécuter directement via l’URL
live.sysinternals.com/<nom_outil>ou le chemin\\live.sysinternals.com\tools\<nom_outil>, et que la liste des outils est consultable sur live.sysinternals.com. ↩ ↩2 -
Microsoft Learn, Debugging Tools for Windows SDK and WDK. Sur le fait que Debugging Tools for Windows est inclus dans le Windows SDK et le WDK, que lancer l’installeur du Windows SDK et ne cocher que « Debugging Tools for Windows » dans la liste des fonctionnalités, en décochant tout le reste, permet d’installer uniquement le débogueur, et que la source de l’installeur est le Windows SDK. ↩ ↩2
-
Microsoft Learn, Install WinDbg. Sur le fait que WinDbg peut servir à l’analyse de dumps de plantage et au débogage en mode utilisateur ou en mode noyau, qu’il peut s’installer directement via l’installeur, via le Microsoft Store, ou avec
winget install Microsoft.WinDbg, et que l’ancien WinDbg (classic) est inclus dans Debugging Tools for Windows. ↩ -
Microsoft Learn, for. Sur le fait qu’il faut écrire
%%variabledans un fichier batch et%variableen exécution directe dans l’invite de commandes, et quefor /fpermet d’analyser la sortie d’une commande. ↩
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Que représente réellement la « mémoire utilisée » sous Windows ── Bien lire Working Set, Private Bytes, Commit et le fichier d'échange
La « mémoire » du Gestionnaire des tâches, Working Set, Private Bytes et Commit ne représentent pas la même valeur. Cet article explique ...
Bonnes pratiques du multithreading en pratique — édition langage C — écrire en toute sécurité à la manière de l'API Win32
Le multithreading en C avec Win32 repose sur des règles éprouvées : création de threads avec _beginthreadex, verrous SRW et variables de ...
Bonnes pratiques de multithreading en pratique — édition C++ : éliminer les accidents structurellement avec RAII et jthread
En C++, le multithreading est un monde où une course de données devient un comportement indéfini. Cet article couvre le piège du destruct...
Bonnes pratiques de multithreading en pratique — édition .NET : ce qu'il faut décider avant d'ajouter des threads
Un ensemble de bonnes pratiques de conception pour .NET/C# afin d'éviter que « démarrer un thread » ne fasse planter ou geler l'applicati...
Cliché instantané de volume (VSS) : fonctionnement et pratique — Pourquoi peut-on sauvegarder des fichiers en cours d'utilisation ?
Un fichier en cours d'utilisation ne peut pas être copié à cause d'une violation de partage, alors comment les logiciels de sauvegarde y ...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Analyse de bugs et incidents de longue durée
Pannes intermittentes, diagnostic des communications, crashs après longue exécution et tests des chemins d'échec.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
Analyse des bugs et des causes
Nous enquêtons sur les pannes difficiles à reproduire, les incidents après longue durée, les fuites et les arrêts de communication.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Pourquoi utiliser spécifiquement Process Explorer alors que le Gestionnaire des tâches existe déjà ?
- Parce que le Gestionnaire des tâches ne permet pas de voir « quel fichier ou objet chaque processus a ouvert » ni « sur quel code chaque thread est actuellement bloqué ». Process Explorer va jusqu'à afficher la liste des handles et des DLL par processus, permet de rechercher un handle par son nom (Ctrl+F), et affiche la pile des threads : l'investigation d'un « fichier impossible à supprimer » ou d'un « blocage » se situe alors dans une tout autre dimension que le Gestionnaire des tâches. En ajoutant les colonnes du nombre de handles ou du nombre d'objets USER/GDI, il peut aussi servir d'outil de surveillance des fuites. Activer Replace Task Manager dans le menu Options remplace tous les appels au Gestionnaire des tâches par Process Explorer, ce qui est une pratique judicieuse à mettre en place sur les machines dédiées à l'investigation.
- En fermant un handle avec l'option -c de handle.exe, peut-on libérer immédiatement le verrou d'un fichier ?
- Techniquement, oui, mais il ne faut fondamentalement pas l'utiliser en production. La documentation officielle elle-même avertit que « fermer un handle peut déstabiliser l'application ou le système ». Comme cela arrache un handle depuis l'extérieur sans tenir compte de l'état interne du processus, le pire des scénarios est possible : au moment où ce processus réutilise plus tard ce même handle, celui-ci pointe désormais vers un autre objet, provoquant un dysfonctionnement (réutilisation de la valeur du handle). La bonne méthode consiste à identifier le processus qui détient le handle et à le terminer proprement. Si le contexte est de vouloir remplacer un exe ou une DLL en cours d'utilisation, envisagez une solution de conception comme Restart Manager.
- Private Bytes ne cesse d'augmenter. Que faire en premier ?
- La première étape consiste à ouvrir le processus concerné dans VMMap pour voir dans quelle catégorie l'augmentation se produit. Si c'est Heap qui augmente, on soupçonne fortement une fuite native via malloc/new/HeapAlloc, et le SDK du fournisseur d'équipement ou du code C++/CLI ou d'interopérabilité devient suspect. Si c'est Managed Heap qui augmente, c'est un problème du tas managé .NET, et il faut alors enquêter sur des références que le GC ne peut pas récupérer (comme un oubli de désabonnement d'un gestionnaire d'événements). Si c'est Private Data (allocation directe via VirtualAlloc) qui augmente, on soupçonne du code ou un SDK qui alloue de gros blocs, comme des tampons d'image. Une fois la catégorie identifiée, passer à l'outil dédié correspondant (WinDbg, PerfView, etc.) évite de s'égarer dans l'investigation.
- Sur un PC d'équipement hors ligne, la pile de l'onglet Threads n'affiche qu'une liste d'adresses illisible. Que faire ?
- Cela vient de l'impossibilité de télécharger les symboles (PDB), et il n'y a que deux solutions : « apporter les symboles » ou « ramener un dump ». Pour apporter les symboles, résolvez-les une fois sur une machine de développement connectée à Internet, avec la même version de l'OS et la même configuration applicative, puis copiez tout le dossier de cache local (par exemple C:\Symbols) sur le PC d'équipement, et configurez le chemin des symboles pour qu'il pointe uniquement vers ce dossier local. Pour ramener un dump, il est plus fiable de capturer un dump pendant le blocage et de l'analyser avec WinDbg sur la machine de développement ; c'est aussi la meilleure option lorsqu'on veut lire précisément la pile d'une application managée. Il est indispensable, en amont, de conserver les PDB de vos propres applications pour chaque build.
- Peut-on installer Process Explorer ou VMMap sans problème sur un PC de production ou d'équipement ?
- Ce sont tous deux des exécutables autonomes ne nécessitant aucune installation, fonctionnant sans inscription au registre ni service résident, ce qui rend leur mise en œuvre peu contraignante. Un accord à l'EULA est requis au premier lancement, et pour un usage scripté, l'acceptation peut être explicitée avec le commutateur /accepteula. Dans un environnement disposant du réseau, il est aussi possible de les exécuter directement depuis Sysinternals Live (https://live.sysinternals.com) sans les télécharger au préalable. Cela dit, si l'observation présente un faible risque, les opérations d'« intervention » comme Kill/Suspend d'un processus, Kill d'un thread, ou la fermeture forcée d'un handle mènent directement à des incidents : en production, contentez-vous d'observer et de consigner, et faites-le dans le cadre du processus habituel d'approbation des travaux.
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.