Utiliser WMI/CIM depuis C# et PowerShell — Guide pratique pour la récupération d'informations matérielles, la surveillance des processus et l'interrogation à distance
· Go Komura · Windows, C#, .NET, PowerShell, WMI, CIM, Application métier, Développement Windows
« Nous voulons afficher le numéro de série et le nom du modèle du PC dans l’écran de l’application métier. » « Nous voulons surveiller l’espace disque libre du serveur et déclencher une alerte. » « Nous voulons détecter le démarrage d’un processus particulier. » « Nous voulons interroger d’un coup l’état de PC situés à distance. » — dans le développement d’applications métier et d’outils d’administration Windows, ce genre de besoin est classique. Et la réponse classique à ce besoin, c’est WMI (Windows Management Instrumentation), ou, pour employer son nom normalisé, CIM (Common Information Model).
Ce qui complique les choses, c’est que les informations sur WMI mélangent l’ancien et le nouveau. Une recherche fait cohabiter des articles vieux de dix ans utilisant Get-WmiObject avec des articles utilisant Get-CimInstance, et côté C#, il existe aussi deux filières : System.Management et Microsoft.Management.Infrastructure. Il est difficile de savoir laquelle est l’écriture actuelle et laquelle « fonctionne encore mais n’est plus à choisir pour du nouveau code ». En pratique, Get-WmiObject n’existe pas dans PowerShell 7, et ce fait surgit brutalement lors de la migration de scripts internes écrits pour 5.1.
Cet article s’adresse aux développeurs C#/PowerShell qui implémentent, dans une application métier, la récupération d’informations matérielles, la surveillance de processus et l’interrogation de PC distants. Il présente, en s’appuyant sur des sources primaires à jour au mois d’août 2026, la compréhension minimale de la structure de WMI/CIM, les applets de commande CIM de PowerShell, les deux API disponibles en C#, des recettes concrètes fréquemment utilisées, les pièges liés aux performances, aux droits et au 64 bits, et enfin les critères permettant de juger « les cas où il ne faut pas utiliser WMI ».
1. Pour commencer, la conclusion
- CIM est la norme industrielle de l’information de gestion établie par le DMTF, et WMI en est l’implémentation Microsoft. Les API de type « CIM » en PowerShell comme en C# sont les API de la génération actuelle conformes à cette norme, mais elles se connectent à la même infrastructure WMI sous-jacente.1
- En PowerShell, l’usage actuel repose sur les applets de commande CIM (Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent). Les anciennes applets de commande WMI (les cinq comme Get-WmiObject) ont été supprimées à partir de PowerShell 6 et ne fonctionnent pas sous PowerShell 7.2
- L’espace de noms par défaut est root/CIMV2, et l’interrogation quotidienne consiste essentiellement à filtrer les classes Win32_* de cet espace avec WQL.3
- L’interrogation à distance passe par défaut par WSMan (WinRM). Spécifier
-ComputerNamecrée une session WSMan temporaire. Pour interroger plusieurs fois la même machine, la bonne pratique en matière de performance consiste à réutiliser une session CIM (New-CimSession) ; pour une machine ancienne sur laquelle WinRM ne peut pas être configuré, il existe une option de protocole DCOM.34 - En C#, il existe deux filières : System.Management (ManagementObjectSearcher) et Microsoft.Management.Infrastructure (CimSession). Les deux sont réservées à Windows et s’installent via NuGet dans le .NET actuel. Pour faire sérieusement de l’interrogation à distance ou de la surveillance, l’API MI, qui partage le même système de types que les applets de commande CIM, est la plus adaptée.56
- Détectez le démarrage des processus par abonnement à des événements, pas par sondage (polling). L’abonnement à
Win32_ProcessStartTracedoit s’exécuter avec des droits administrateur.78 - N’utilisez pas
SELECT *par facilité. Restreindre les données transférées avec-Filter/-Property/-KeyOnlyprévient la moitié des problèmes de performance de WMI.3 - WMI n’est pas une solution universelle. Pour la surveillance de performance à haute fréquence, la lecture/écriture de la configuration de votre propre application ou un appel ponctuel à une fonctionnalité de l’OS, les compteurs de performance, le registre, l’API Win32 ou des applets de commande dédiées sont mieux adaptés (voir le tableau de décision du chapitre 8).
2. Qu’est-ce que WMI/CIM ? — Norme et implémentation, espaces de noms, classes, WQL
Commençons par clarifier une bonne fois pour toutes les relations entre ces termes.
| Terme | Nature |
|---|---|
| CIM (Common Information Model) | Modèle standard de l’industrie permettant de représenter les objets gérés — systèmes, applications, réseaux, périphériques, etc. Élaboré et maintenu par le DMTF (Distributed Management Task Force)1 |
| WBEM (Web-Based Enterprise Management) | Initiative de l’industrie visant à créer des technologies standard d’accès aux informations de gestion dans un environnement d’entreprise1 |
| WMI | Implémentation Microsoft de WBEM. Représente les objets gérés à l’aide de la norme CIM et est intégré à Windows1 |
| MI (Windows Management Infrastructure) | Version de nouvelle génération de WMI. Totalement compatible avec le WMI traditionnel ; la plupart des nouveaux fournisseurs sont écrits en MI1 |
Il y a quatre éléments structurels que tout développeur doit connaître.
- Espace de noms (namespace) : une hiérarchie qui regroupe les classes. Pour l’interrogation quotidienne, on utilise presque toujours root/CIMV2, qui est aussi l’espace de noms par défaut des applets de commande CIM.3 Il en existe d’autres, comme
root\default(fournisseur du registre, etc.). - Classe : un type d’objet géré, comme
Win32_ComputerSystem(l’ordinateur lui-même),Win32_LogicalDisk(un lecteur logique) ouWin32_Process(un processus). Les classes propres à Windows qui héritent des classes de la norme CIM (commeCIM_LogicalDisk) portent le préfixeWin32_.9 - Fournisseur (provider) : le composant qui fournit le contenu concret d’une classe. Lors d’une interrogation, le fournisseur interroge l’OS à la volée et construit les valeurs.
- WQL : un langage de requête proche du SQL. Comme dans
SELECT Name, State FROM Win32_Service WHERE StartMode = 'Auto', on traite les classes comme des tables pour les filtrer. WQL est aussi le langage de requête par défaut des applets de commande CIM.3
« Pouvoir lire les informations de l’OS et du matériel via des classes et un langage de requête unifiés » : voilà la valeur de WMI. À l’inverse, l’écriture ou les opérations se limitent aux classes qui possèdent des méthodes appelables via Invoke-CimMethod : ce n’est pas un mécanisme capable de tout faire.
3. Utilisation depuis PowerShell — les applets de commande CIM sont l’usage actuel, les applets de commande WMI ont été supprimées
3.1. La base : Get-CimInstance
# Spécifier la classe (espace de noms par défaut root/CIMV2)
Get-CimInstance -ClassName Win32_OperatingSystem
# N'écrire que la clause WHERE dans -Filter (sans le mot-clé WHERE)
Get-CimInstance -ClassName Win32_Service -Filter "StartMode = 'Auto' AND State <> 'Running'"
# Ne récupérer que les propriétés nécessaires pour réduire le volume transféré
Get-CimInstance -ClassName Win32_Process -Property Name, ProcessId, CreationDate
# Pour écrire du WQL directement, utiliser -Query
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name LIKE 'p%'"
-Filter correspond exactement à la clause WHERE de WQL, et -Property limite les colonnes récupérées.3 La valeur de retour est un objet CimInstance, et les propriétés de date (comme CreationDate ou LastBootUpTime) sont renvoyées déjà converties en DateTime. Contrairement à l’ancien Get-WmiObject, l’objet obtenu ne possède pas directement de méthodes : pour appeler une méthode, il faut passer par Invoke-CimMethod.
# Appeler une méthode d'instance : récupérer le propriétaire de chaque processus
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" |
Invoke-CimMethod -MethodName GetOwner
# Appeler une méthode statique de la classe : démarrer un processus
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = 'notepad.exe' }
# Examiner la définition de la classe (liste des propriétés et méthodes)
Get-CimClass -ClassName Win32_Process
3.2. Tableau de correspondance pour migrer depuis les anciennes applets de commande WMI
À partir de PowerShell 6 (donc dans PowerShell 7, la version actuelle), les applets de commande WMI v1 suivantes ont été supprimées. Les mêmes fonctionnalités sont fournies par le module CimCmdlets (WMI v2).2
| Ancien (jusqu’à Windows PowerShell 5.1) | Actuel (applets de commande CIM) | Remarque |
|---|---|---|
Get-WmiObject |
Get-CimInstance |
Le principe de -Filter / -Query est identique |
Get-WmiObject -List |
Get-CimClass |
Exploration des classes, vérification de leur définition |
Invoke-WmiMethod |
Invoke-CimMethod |
Les arguments se passent via une table de hachage -Arguments @{ } |
Register-WmiEvent |
Register-CimIndicationEvent |
Abonnement à des événements (section 6.3) |
Set-WmiInstance |
Set-CimInstance |
Modification des propriétés inscriptibles |
Remove-WmiObject |
Remove-CimInstance |
Suppression d’une instance |
Comme les applets de commande CIM fonctionnent déjà sous Windows PowerShell 5.1, écrire tout nouveau code côté CIM, même s’il doit tourner sous 5.1, est la façon d’écrire qui ne laisse aucun coût de migration derrière soi. Nous avons dressé un panorama complet de la coexistence et de la migration entre 5.1 et 7 dans « Les différences entre Windows PowerShell 5.1 et PowerShell 7 ».
4. Interrogation à distance — sessions CIM (WSMan par défaut) et option DCOM
Les applets de commande CIM se connectent en COM au WMI local si rien n’est précisé, et créent une session temporaire via le protocole WSMan (WinRM) lorsque -ComputerName est spécifié. Si vous effectuez plusieurs opérations sur le même ordinateur, il est plus avantageux, en termes de performance, de créer une session CIM et de la réutiliser.3
# Pour une opération ponctuelle : -ComputerName (une session temporaire est créée à chaque fois)
Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName Server01, Server02
# Pour des interrogations répétées : réutiliser une session CIM
$session = New-CimSession -ComputerName Server01
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $session
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" -CimSession $session
Remove-CimSession $session
Pour une machine ancienne sur laquelle WinRM ne peut pas être configuré, ou plus généralement toute machine injoignable en WSMan, vous pouvez choisir le protocole DCOM.4
$dcom = New-CimSessionOption -Protocol Dcom
$session = New-CimSession -ComputerName OldServer -SessionOption $dcom
Voici les prérequis pour l’interrogation à distance.
- WinRM doit être configuré sur la machine cible.
winrm quickconfigeffectue en une seule fois le démarrage automatique du service, la création de l’écouteur HTTP (port par défaut 5985) et l’enregistrement de l’exception de pare-feu.10 Pour se connecter en HTTPS (port par défaut 5986), cela ne suffit pas : il faut préparer un certificat serveur puis configurer séparément un écouteur HTTPS, par exemple avecwinrm quickconfig -transport:https.10 - Le port correspondant doit être ouvert sur le pare-feu du chemin réseau. La conception et l’enregistrement pratiques des règles de trafic entrant sont traités dans l’article « Le pare-feu Windows et les applications métier ».
- Authentification. Dans un environnement de domaine, l’authentification mutuelle se fait via Kerberos. Dans un groupe de travail, Kerberos n’est pas utilisable, ce qui peut nécessiter d’inscrire la machine dans les
TrustedHostscôté client. Limitez cette inscription au strict nécessaire.10 - Droits. Dans la configuration par défaut, l’interrogation et l’exploitation de WMI à distance se font en principe avec un compte appartenant au groupe des administrateurs de la machine cible. Pour l’ouvrir à des utilisateurs standard, il faut configurer les autorisations à la fois côté WinRM et côté espace de noms WMI.10
- Notez enfin que DCOM n’a pas de port d’écoute fixe (il utilise les ports dynamiques du RPC), ce qui rend sa conception à travers un pare-feu plus difficile. Pour tout nouveau mécanisme, il est plus sûr de considérer WSMan comme le choix par défaut.
5. Utilisation depuis C# — System.Management et Microsoft.Management.Infrastructure
Il existe deux filières d’API pour utiliser WMI depuis C#. Toutes deux sont réservées à Windows.
| System.Management | Microsoft.Management.Infrastructure (API MI) | |
|---|---|---|
| Installation | Standard dans .NET Framework. Dans le .NET actuel, paquet NuGet System.Management5 | Paquet NuGet Microsoft.Management.Infrastructure6 |
| Classe d’entrée | ManagementObjectSearcher (interroger en passant du WQL)5 |
CimSession (Create → QueryInstances / InvokeMethod / Subscribe)6 |
| Système de types | ManagementObject / ManagementEventWatcher11 |
CimInstance / CimSession — les mêmes types que les applets de commande CIM3 |
| À distance | Basé sur DCOM | Basé sur WSMan (session CIM). Existe en version asynchrone (*Async)6 |
| Cas d’usage adapté | Récupération d’informations locales. Maintenance d’une base de code existante | Intégration d’interrogation/surveillance à distance. Conception associée à PowerShell |
5.1. System.Management : les bases de ManagementObjectSearcher
On passe une requête WQL sous forme de chaîne et on récupère la collection de résultats avec Get().5
// NuGet : System.Management (réservé à Windows)
using System.Management;
using var searcher = new ManagementObjectSearcher(
@"root\cimv2",
"SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");
foreach (ManagementObject disk in searcher.Get())
{
var freeGb = (ulong)disk["FreeSpace"] / 1024.0 / 1024.0 / 1024.0;
var sizeGb = (ulong)disk["Size"] / 1024.0 / 1024.0 / 1024.0;
Console.WriteLine($"{disk["DeviceID"]} libre {freeGb:F1} Go / total {sizeGb:F1} Go");
}
Les propriétés sont renvoyées comme object via l’indexeur : il faut donc consulter la documentation de la classe pour connaître le type CIM (dans cet exemple, FreeSpace / Size sont de type uint649) avant de faire la conversion. Le premier écueil classique consiste à présumer un type int et à provoquer ainsi une InvalidCastException.
5.2. API MI : les bases de CimSession
CimSession traite le local et le distant de la même manière. Elle couvre l’énumération, l’interrogation, l’appel de méthodes, l’abonnement aux événements, ainsi que leurs versions asynchrones.6
// NuGet : Microsoft.Management.Infrastructure (réservé à Windows)
using Microsoft.Management.Infrastructure;
// En local : CimSession.Create(null) ; à distance : passer le nom de la machine
using CimSession session = CimSession.Create(null);
IEnumerable<CimInstance> disks = session.QueryInstances(
@"root\cimv2", "WQL",
"SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");
foreach (CimInstance disk in disks)
{
var deviceId = (string)disk.CimInstanceProperties["DeviceID"].Value;
var free = (ulong)disk.CimInstanceProperties["FreeSpace"].Value;
Console.WriteLine($"{deviceId} libre {free / 1024.0 / 1024 / 1024:F1} Go");
}
Comme on manipule le même CimInstance que celui renvoyé par les applets de commande CIM de PowerShell, le flux de développement « essayer d’abord en PowerShell puis reporter en C# » s’enchaîne naturellement. Si vous concevez vous-même l’articulation entre C# et PowerShell, consultez aussi « Exécuter PowerShell depuis C# et récupérer le résultat sous forme d’objets ».
6. Recettes concrètes fréquemment utilisées
6.1. Aide-mémoire des classes classiques
| Information recherchée | Classe | Principales propriétés |
|---|---|---|
| Fabricant, nom du modèle | Win32_ComputerSystem |
Manufacturer, Model |
| Numéro de série du PC | Win32_BIOS |
SerialNumber |
| Version de l’OS, heure de démarrage | Win32_OperatingSystem |
Caption, Version, LastBootUpTime |
| Espace disque libre | Win32_LogicalDisk |
DeviceID, FreeSpace, Size, DriveType9 |
| État des services | Win32_Service |
Name, State, StartMode |
| Liste des processus | Win32_Process |
Name, ProcessId, CommandLine |
6.2. Le classique de la gestion d’actifs : numéro de série, nom de modèle, espace disque libre
# Informations de modèle et numéro de série (pour le rapprochement avec le registre des actifs PC)
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -Property Manufacturer, Model
$bios = Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber
[pscustomobject]@{
Manufacturer = $cs.Manufacturer
Model = $cs.Model
Serial = $bios.SerialNumber
}
# Espace libre des disques locaux (DriveType = 3)
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" |
Select-Object DeviceID,
@{ Name = 'FreeGB'; Expression = { [math]::Round($_.FreeSpace / 1GB, 1) } },
@{ Name = 'SizeGB'; Expression = { [math]::Round($_.Size / 1GB, 1) } }
DriveType = 3 désigne un « disque local », ce qui exclut les lecteurs amovibles (2), les lecteurs réseau (4) et les CD (5).9 Pour de la surveillance, il suffit de faire tourner ce script sur chaque serveur via une session CIM pour obtenir la base d’une surveillance de disque sans agent.
6.3. Détecter le démarrage d’un processus — abonnement à des événements
Plutôt que de « sonder Win32_Process périodiquement et regarder les différences » (polling), optez pour un abonnement à des événements. Le plus simple pour le démarrage d’un processus est de s’abonner à Win32_ProcessStartTrace (une classe d’événement du fournisseur de trace du noyau, qui possède des propriétés comme ProcessName / ProcessID / ParentProcessID8).
# À exécuter dans un PowerShell lancé avec des droits administrateur
$action = {
$name = $Event.SourceEventArgs.NewEvent.ProcessName
$id = $Event.SourceEventArgs.NewEvent.ProcessID
Write-Host "Démarrage du processus : $name (PID=$id)"
}
Register-CimIndicationEvent -ClassName Win32_ProcessStartTrace `
-SourceIdentifier ProcessStarted -Action $action
L’abonnement reste actif tant que la session PowerShell dans laquelle l’enregistrement a été fait est vivante, et -Action s’exécute à chaque démarrage de processus. Attention : si vous enchaînez tout de suite avec la commande de désinscription, l’abonnement disparaît avant même que la surveillance ne commence. La désinscription s’exécute au moment où vous arrêtez la surveillance.
# Au moment d'arrêter la surveillance : désinscription de l'abonnement
Unregister-Event -SourceIdentifier ProcessStarted
Register-CimIndicationEvent enregistre un abonnement à partir d’un nom de classe ou d’une requête d’événement WQL, et le bloc de script -Action s’exécute à chaque événement reçu.7 L’abonnement à cette classe nécessite des droits administrateur.7 Qui peut recevoir l’événement est contrôlé par le descripteur de sécurité de la classe d’événement, et un utilisateur standard se voit refuser l’accès.8
Une autre méthode consiste à utiliser l’événement de création d’instance (__InstanceCreationEvent), un mécanisme générique applicable à n’importe quelle classe. Il s’agit d’un mécanisme où WMI sonde à l’intervalle indiqué par WITHIN et transforme les différences en événements : c’est donc à vous de décider du compromis entre intervalle de détection et charge.
# Surveiller les nouvelles instances de Win32_Process avec un sondage toutes les 5 secondes
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier ProcPoll -Action {
Write-Host "Démarrage : $($Event.SourceEventArgs.NewEvent.TargetInstance.Name)"
}
En C# (System.Management), ManagementEventWatcher joue le même rôle.11
using System.Management;
// Dans un processus exécuté en tant qu'administrateur
var watcher = new ManagementEventWatcher(
new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
watcher.EventArrived += (_, e) =>
{
var name = (string)e.NewEvent["ProcessName"];
var pid = (uint)e.NewEvent["ProcessID"];
Console.WriteLine($"Démarrage du processus : {name} (PID={pid})");
};
watcher.Start();
// Ne pas oublier watcher.Stop() et Dispose à la fin de la surveillance
Si vous intégrez cela dans une surveillance résidente, incluez dans la conception la réinscription en cas de coupure de l’abonnement (au redémarrage du service, en cas d’erreur). La réflexion sur la conception de la « vérification et de l’affichage de l’état », y compris la surveillance de périphériques, est traitée dans « Bonnes pratiques pour la vérification et l’affichage de l’état d’un périphérique externe ».
7. Pièges — performance, droits, 64 bits, dépôt et dates
7.1. L’abus de SELECT * et du sondage
Une interrogation WMI, c’est « le fournisseur qui construit les valeurs à la volée » : ce n’est pas gratuit. Il existe deux anti-modèles classiques.
- L’usage paresseux de
SELECT *. Récupérer toutes les instances deWin32_Processavec toutes leurs propriétés fait gonfler d’autant le travail du fournisseur et le trafic réseau (en cas d’interrogation à distance). Filtrez les lignes avec-Filteret les colonnes avec-Property, et utilisez-KeyOnlysi vous n’avez besoin que des clés pour une opération ultérieure. Ce sont tous des moyens officiellement prévus « pour réduire la taille des objets et le trafic réseau ».3 - Le sondage à intervalle court. Une conception du type «
Get-CimInstance Win32_Processtoutes les secondes » doit être remplacée par l’abonnement à des événements de la section 6.3. Si vous devez absolument utiliser le sondage (WITHIN), élargissez l’intervalle jusqu’au minimum nécessaire et suffisant pour vos besoins.
De même, répéter -ComputerName machine par machine vers des cibles distantes est très gaspilleur : une session temporaire est créée à chaque interrogation. Pour plusieurs opérations, passez à la réutilisation d’une session CIM.3
7.2. Les droits nécessaires à l’abonnement aux événements
Comme indiqué en section 6.3, l’abonnement aux classes du type Win32_ProcessStartTrace suppose des droits administrateur.7 L’incident « ça marchait sur la machine de développement (lancée en administrateur), mais la surveillance ne fonctionne pas chez le client en environnement utilisateur standard » est un classique, au même titre que les boîtes de dialogue de notification du pare-feu. Si vous intégrez une surveillance dans une application métier destinée à tourner sous un compte utilisateur standard, envisagez de séparer la partie surveillance dans un service Windows (LocalSystem, etc.) relié à l’application principale par communication interprocessus.
7.3. 32 bits / 64 bits et les fournisseurs
Sous Windows 64 bits, certains fournisseurs existent à la fois en version 32 bits et 64 bits, et par défaut, c’est la version correspondant au nombre de bits de l’application appelante qui répond.12 L’exemple typique est le fournisseur de registre StdRegProv de root\default : une lecture depuis une application 32 bits renvoie les valeurs du côté Wow6432Node (la vue 32 bits).12 Si « la valeur de registre lue via WMI diffère de celle vue dans regedit », commencez par soupçonner ce point. Si vous avez besoin de la vue opposée, vous pouvez la demander explicitement en spécifiant __ProviderArchitecture (et, pour la rendre obligatoire, __RequiredArchitecture) dans le contexte de connexion.12 Le panorama complet de ce problème de nombre de bits est également traité dans « Appeler l’API Win32 en toute sécurité depuis C# — guide pratique P/Invoke ».
7.4. Symptômes et traitement en cas de corruption du dépôt WMI
Les définitions de classes WMI sont stockées dans un dépôt (repository) — non pas un fichier unique, mais un ensemble de fichiers du dossier Repository qui fait office de base de données13. Lorsque ce dépôt devient incohérent, des erreurs telles que « une classe censée exister est introuvable » ou « l’espace de noms est invalide » commencent à apparaître alors même que vous n’avez rien changé côté application. Utilisez winmgmt.exe pour le diagnostic et la réparation.13
rem Vérification de la cohérence (un résultat "inconsistent" indique un problème)
winmgmt /verifyrepository
rem Vérification de la cohérence + reconstruction en cas d'incohérence (le contenu lisible est fusionné)
winmgmt /salvagerepository
Le point à surveiller, c’est de ne pas faire de la suppression ou de la réinitialisation du dépôt le premier réflexe. Les erreurs qui remontent via WMI peuvent avoir leur origine ailleurs dans l’OS, et Microsoft précise explicitement que faire de la suppression du dépôt le premier traitement « peut endommager le système ou les applications installées ».13 Respectez l’ordre : vérification avec /verifyrepository → réparation avec /salvagerepository.
7.5. La conversion du format de date DMTF
Les dates WMI sont stockées sous forme de chaîne au format DMTF yyyymmddHHMMSS.mmmmmm±UUU de la spécification CIM (le suffixe étant le décalage en minutes par rapport à l’UTC ; par exemple 20260801100000.000000+540). N’essayez pas de découper la valeur brute par manipulation de chaînes : utilisez une API de conversion.
- C# (System.Management) :
ManagementDateTimeConverterfournit la conversion bidirectionnelle entre le format DMTF etDateTime/TimeSpan.11 - API de type CIM (Get-CimInstance / API MI) : les propriétés de date sont renvoyées déjà converties en
DateTime, si bien que ce problème ne se pose tout simplement pas.(Get-CimInstance Win32_OperatingSystem).LastBootUpTimepeut être utilisé directement comme unDateTimedans un calcul.
8. Les cas où il ne faut pas utiliser WMI — tableau de décision des moyens
WMI est excellent en tant que « point de lecture unifié », mais ce n’est pas toujours la meilleure solution. Voici des repères pratiques pour bien choisir.
| Ce que vous voulez faire | Moyen adapté | Pourquoi ne pas choisir WMI |
|---|---|---|
| Récupération d’informations matérielles et de la configuration de l’OS, interrogation à distance sans agent | WMI/CIM | C’est là le domaine de prédilection de WMI : plus unifié que d’appeler des API dédiées une à une |
| Lecture/écriture de la configuration de votre propre application | Lecture directe du registre (Microsoft.Win32.Registry), fichier de configuration |
Manipuler le registre via WMI est un détour et hérite du problème de bits de la section 7.3 |
| Surveillance de performance fréquente et continue (utilisation CPU, etc.) | Compteurs de performance (System.Diagnostics.PerformanceCounter, etc.) |
Les compteurs sont conçus pour cela ; le sondage à court intervalle de WMI est désavantagé en charge et en précision |
| Appel ponctuel à une fonctionnalité de l’OS, traitement nécessitant une faible latence | API Win32 (P/Invoke) | WMI ajoute une surcharge en passant par COM/le fournisseur |
| Énumération/manipulation locale de processus, réalisable avec les droits de votre propre processus | System.Diagnostics.Process |
Autosuffisant avec la bibliothèque standard, moins de dépendances |
| Configuration de fonctionnalités d’administration Windows (pare-feu, réseau, etc.) | Applets de commande dédiées basées sur CIM, comme Get-NetFirewallRule |
Des applets de commande organisées par usage sont plus précises et plus sûres que de chercher soi-même les classes WMI brutes |
| Détection de modification de fichiers/dossiers | FileSystemWatcher |
Ne recourez pas à WMI dans un domaine qui dispose déjà d’une API dédiée |
Le critère de décision est simple : « utilisez le mécanisme dédié là où il en existe un, et réservez WMI/CIM à l’interrogation transversale et à l’interrogation à distance. » Les applets de commande de la dernière ligne, comme Get-NetFirewallRule, sont en interne construites sur CIM : on peut dire qu’elles permettent d’« obtenir les bénéfices de WMI/CIM sans le manipuler directement ».
9. Conclusion
- CIM est la norme industrielle du DMTF, et WMI en est l’implémentation Microsoft. Aussi bien les applets de commande CIM de PowerShell que l’API MI de C# sont les points d’entrée de la génération actuelle conformes à cette norme.
- En PowerShell, l’usage actuel repose sur Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent. Les applets de commande WMI comme Get-WmiObject n’existent pas dans PowerShell 7 : écrivez donc tout nouveau script côté CIM, même s’il vise 5.1.
- L’interrogation à distance passe par défaut par WSMan (WinRM), et pour plusieurs opérations, réutilisez une session CIM. Pour une machine sans WinRM configuré, l’option DCOM offre une échappatoire.
- En C#, choisissez entre System.Management (simple, adapté au local) et Microsoft.Management.Infrastructure (adapté au distant et à la surveillance, avec le même système de types que les applets de commande CIM). Les deux sont des paquets NuGet réservés à Windows.
- Surveillez les processus par abonnement à des événements, pas par sondage. L’abonnement à Win32_ProcessStartTrace nécessite des droits administrateur.
- Évitez SELECT * et le sondage à court intervalle : filtrez avec -Filter / -Property / -KeyOnly. Retenez qu’une interrogation depuis un processus 32 bits est dirigée vers le fournisseur 32 bits, que les dates DMTF doivent passer par l’API de conversion, et qu’en cas de corruption du dépôt, il faut procéder par verify puis salvage plutôt que par suppression.
- Ne recourez pas à WMI dans les domaines qui disposent déjà d’un mécanisme dédié (configuration, compteurs de performance, appel ponctuel à une API) ; réservez WMI/CIM à l’interrogation transversale et à l’interrogation à distance — c’est en une phrase la règle d’usage.
Articles connexes
- Exécuter PowerShell depuis C# et récupérer le résultat sous forme d’objets
- Recueil de commandes PowerShell pratiques — élargir la panoplie des petites fonctions utiles au quotidien
- Les différences entre Windows PowerShell 5.1 et PowerShell 7 — guide pratique de migration des scripts internes
- Bonnes pratiques pour la vérification et l’affichage de l’état d’un périphérique externe — une conception qui ne se contente pas de « connecté »
- Appeler l’API Win32 en toute sécurité depuis C# — guide pratique P/Invoke (DllImport / LibraryImport / CsWin32)
- Qu’est-ce que le TPM sous Windows ? — le « coffre-fort qui ne laisse jamais sortir la clé » et le démarrage mesuré, expliqués en images
Domaines de conseil associés
合同会社小村ソフト (Komura Software LLC) prend en charge l’intégration de la récupération d’informations matérielles, de la surveillance de processus et de l’interrogation de PC distants avec WMI/CIM dans des applications métier, la migration de scripts internes basés sur Get-WmiObject vers les applets de commande CIM, ainsi que l’investigation de cas du type « ça marche sur la machine de développement mais on obtient une erreur de droits chez le client ». Vous pouvez nous consulter pour tout l’enchaînement, du prototypage en PowerShell jusqu’à l’implémentation complète en C#.
- Développement d’applications Windows
- Investigation de dysfonctionnements et analyse de cause
- Conseil technique et revue de conception
- Contact
Références
-
Microsoft Learn, About WMI. Sur le fait que WMI est l’implémentation Microsoft de WBEM (une initiative de l’industrie développant des technologies standard d’accès aux informations de gestion en environnement d’entreprise), que la représentation des objets gérés utilise la norme industrielle CIM (Common Information Model) développée et maintenue par le DMTF (Distributed Management Task Force), que la version de nouvelle génération MI (Windows Management Infrastructure) est totalement compatible avec le WMI traditionnel, et que les connexions WMI distantes se font en DCOM, avec WinRM basé sur WS-Management comme alternative. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. Sur la suppression des applets de commande WMI v1 (Register-WmiEvent / Set-WmiInstance / Invoke-WmiMethod / Get-WmiObject / Remove-WmiObject) de PowerShell, et sur le fait que les applets de commande du module CimCmdlets (WMI v2) offrent les mêmes fonctionnalités avec de nouvelles capacités et une syntaxe repensée. ↩ ↩2
-
Microsoft Learn, Get-CimInstance (CimCmdlets). Sur le fait que, sans ComputerName ni CimSession, la connexion à WMI local se fait via une session COM, et qu’avec -ComputerName une session temporaire en protocole WsMan est créée ; sur le fait que la connexion via une session CIM est recommandée, pour des raisons de performance, pour plusieurs opérations sur le même ordinateur ; sur le fait que -Filter est la clause where de WQL/CQL sans le mot-clé WHERE ; sur le fait que -Property et -KeyOnly permettent de réduire la taille des objets et le trafic réseau ; sur le fait que l’espace de noms par défaut est root/CIMV2 et que le langage de requête par défaut (-QueryDialect) est WQL ; sur le fait que la sortie est de type Microsoft.Management.Infrastructure.CimInstance ; sur un exemple d’appel de GetOwner combiné à Invoke-CimMethod ; et sur le fait qu’il s’agit d’applets de commande réservées à Windows. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, New-CimSessionOption (CimCmdlets). Sur le fait qu’il existe deux jeux de paramètres pour les options de session CIM, l’un pour WsMan et l’autre pour DCOM ; sur les valeurs possibles de -Protocol (Dcom / Default / Wsman) ; sur un exemple créant une session CIM DCOM en passant à -SessionOption de New-CimSession l’option créée avec New-CimSessionOption -Protocol Dcom ; et sur le fait que le niveau d’emprunt d’identité par défaut d’une session DCOM est Impersonate. ↩ ↩2
-
Microsoft Learn, ManagementObjectSearcher Class (System.Management). Sur le fait qu’il s’agit de la classe d’entrée la plus courante pour récupérer des informations de gestion, obtenant une collection d’objets de gestion à partir d’une requête WQL donnée ; sur le fait qu’elle reçoit un ObjectQuery et un ManagementScope (espace de noms WMI) et renvoie un ManagementObjectCollection via Get() ; et sur le fait que System.Management.dll est fourni sous forme de paquet NuGet System.Management. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, CimSession Class (Microsoft.Management.Infrastructure). Sur le fait que Microsoft.Management.Infrastructure.dll est fourni sous forme de paquet NuGet Microsoft.Management.Infrastructure ; sur la création de session via Create(computerName) ; sur l’exécution de requêtes via QueryInstances(namespace, queryDialect, query) ; et sur le fait que la classe dispose de EnumerateInstances / GetInstance / InvokeMethod / Subscribe ainsi que de leurs versions asynchrones respectives (*Async), et implémente IDisposable. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Register-CimIndicationEvent (CimCmdlets). Sur l’abonnement à une indication (événement) par nom de classe ou par expression de requête, avec un nom d’abonnement donné via -SourceIdentifier ; sur l’exemple d’abonnement à Win32_ProcessStartTrace et la remarque selon laquelle son exécution nécessite un PowerShell lancé en administrateur ; sur l’exemple de référencement de ProcessName / ProcessId depuis $Event.SourceEventArgs.NewEvent dans le bloc de script -Action ; sur le fait que -ComputerName crée une session WsMan temporaire, et qu’en son absence la connexion se fait localement en COM ; et sur l’utilisation d’Unregister-Event pour désinscrire l’abonnement. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Win32_ProcessStartTrace class. Sur le fait qu’il s’agit d’une classe d’événement signalant le démarrage d’un nouveau processus, dotée de propriétés comme ProcessName / ProcessID / ParentProcessID / SessionID / Sid ; sur le fait que la propriété SECURITY_DESCRIPTOR est le descripteur permettant au fournisseur d’événements de déterminer quels utilisateurs peuvent recevoir l’événement ; et sur le fait que l’espace de noms est Root\CIMV2, fourni par le fournisseur de trace du noyau (Krnlprov.dll). ↩ ↩2 ↩3
-
Microsoft Learn, Win32_LogicalDisk class. Sur le fait que Win32_LogicalDisk est une classe dérivée de CIM_LogicalDisk représentant un périphérique de stockage local ; sur les valeurs de DriveType (2 = amovible, 3 = disque local, 4 = lecteur réseau, 5 = CD, etc.) ; sur le fait que FreeSpace / Size sont des valeurs en octets de type uint64 ; sur le fait que DeviceID est la clé ; et sur des exemples de requêtes VBScript / C# filtrant sur DriveType = 3. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Installation and configuration for Windows Remote Management. Sur le fait que, par défaut, aucun écouteur WinRM n’est configuré et que les messages WS-Management ne peuvent pas être envoyés ni reçus ; sur le fait que winrm quickconfig effectue le démarrage automatique du service, la configuration des écouteurs HTTP/HTTPS et l’enregistrement de l’exception de pare-feu ; sur le fait que les ports par défaut de WinRM 2.0 sont 5985 en HTTP et 5986 en HTTPS ; sur le fait qu’en cas d’impossibilité d’établir une authentification mutuelle (Kerberos), par exemple dans un groupe de travail, il faut configurer les TrustedHosts de façon aussi restreinte que possible ; et sur le descripteur de sécurité par défaut (RootSDDL) contrôlant l’accès distant à l’écouteur, ainsi que sur la configuration supplémentaire nécessaire pour autoriser des utilisateurs non administrateurs à utiliser un plug-in WMI. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, System.Management Namespace. Sur le fait qu’il s’agit de l’espace de noms où l’interrogation de l’infrastructure WMI se fait via les classes de type ManagementObjectSearcher et l’abonnement aux événements via ManagementEventWatcher ; sur le fait que WqlEventQuery représente une requête d’événement au format WQL ; et sur le fait que ManagementDateTimeConverter fournit des méthodes de conversion bidirectionnelle entre les dates/heures et intervalles de temps DMTF et les DateTime / TimeSpan du CLR. ↩ ↩2 ↩3
-
Microsoft Learn, Requesting WMI Data on a 64-bit Platform. Sur le fait que, lorsqu’un fournisseur existe à la fois en version 32 bits et 64 bits, c’est par défaut le fournisseur 32 bits qui répond à une application 32 bits (scripts compris), et le fournisseur 64 bits à une application 64 bits ; sur la possibilité de demander ou d’imposer le fournisseur non par défaut via __ProviderArchitecture (32 ou 64) et __RequiredArchitecture dans le contexte (avec une erreur WBEM_E_PROVIDER_LOAD_FAILURE si la version imposée n’existe pas) ; et sur l’exemple du fournisseur de registre où un client 32 bits reçoit les données du côté HKLM\SOFTWARE\Wow6432Node. ↩ ↩2 ↩3
-
Microsoft Learn, winmgmt. Sur le fait que /verifyrepository de winmgmt.exe effectue une vérification de cohérence du dépôt WMI ; que /salvagerepository effectue cette vérification et, en cas d’incohérence, reconstruit le dépôt en fusionnant le contenu lisible ; que /resetrepository ramène le dépôt à son état d’installation initiale de l’OS ; que le dépôt fonctionne comme une base de données constituée d’un ensemble de fichiers du dossier Repository ; et que les erreurs remontant via WMI peuvent avoir leur origine ailleurs dans l’OS, si bien que la suppression du dépôt ne doit pas être le premier traitement, car elle peut endommager le système ou les applications installées. ↩ ↩2 ↩3
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
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...
Empêcher les lancements multiples d'une application Windows — Mutex nommé et activation de la fenêtre existante lors d'un second lancement
Cet article détaille comment implémenter la prévention des lancements multiples d'une application Windows métier à l'aide d'un Mutex nomm...
Externalisation et développement sur mesure d'une application Windows : ce qu'il faut clarifier avant de se lancer
Avant de confier l'externalisation ou le développement sur mesure d'une application Windows, voici les points à clarifier : révision d'un...
Comment exécuter PowerShell depuis C# (CSharp) et récupérer le résultat sous forme d'objets
Comment lancer PowerShell depuis C# et récupérer le résultat sous forme de PSObject plutôt que de chaînes de caractères : un tour d'horiz...
Guide pratique du magasin de certificats Windows — Faut-il l'installer côté utilisateur ou côté ordinateur ?
Faut-il placer un certificat client dans le magasin utilisateur ou dans le magasin ordinateur ? Ce guide pratique règle méthodiquement le...
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.
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.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Quelle est la différence entre WMI et CIM ?
- CIM est le « modèle standard de l'industrie permettant de représenter les objets gérés tels que les systèmes ou les périphériques », élaboré et maintenu par le DMTF (Distributed Management Task Force). WMI est l'implémentation Microsoft de cette norme dans le cadre de l'initiative WBEM, et il est intégré à Windows. Autrement dit, CIM est la spécification et WMI l'implémentation sur Windows. Si Get-CimInstance en PowerShell ou Microsoft.Management.Infrastructure en C# se réclament du « CIM », c'est parce que ce sont des API conformes à cette norme, mais elles se connectent toutes les deux à la même infrastructure WMI sous-jacente. Au quotidien, il suffit de retenir qu'on « interroge les classes WMI (Win32_* etc.) via des API de type CIM » pour ne pas être gêné en pratique.
- Get-WmiObject n'est-il plus utilisable ?
- Il fonctionne toujours sous Windows PowerShell 5.1, mais à partir de PowerShell 6 (et donc dans PowerShell 7, la version actuelle), les applets de commande WMI v1 — Get-WmiObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance et Remove-WmiObject — ont été supprimées et ne peuvent plus être exécutées. Les mêmes fonctionnalités sont fournies par le module CimCmdlets (Get-CimInstance, Invoke-CimMethod, Register-CimIndicationEvent, etc.). Pour tout nouveau script, il est plus sûr d'utiliser directement les applets de commande CIM, même si le script doit tourner sous 5.1 : cela évite d'avoir à réécrire la partie WMI lors d'une future migration vers PowerShell 7.
- Pour utiliser WMI depuis C#, faut-il choisir System.Management ou Microsoft.Management.Infrastructure ?
- Les deux sont réservés à Windows, et depuis le .NET actuel, on les installe via un paquet NuGet. System.Management est l'API classique : il suffit de passer une requête WQL à ManagementObjectSearcher, et cela suffit amplement si l'essentiel est la récupération d'informations locales. Le convertisseur de dates DMTF, ManagementDateTimeConverter, en fait également partie. Microsoft.Management.Infrastructure (l'API MI), de son côté, partage le même système de types que les applets de commande CIM de PowerShell (CimSession / CimInstance) et gère de façon cohérente l'interrogation à distance via WSMan, les méthodes en version asynchrone et l'abonnement aux événements (Subscribe). Si vous voulez intégrer sérieusement l'interrogation ou la surveillance de PC distants, il est raisonnable de choisir l'API MI.
- Get-CimInstance ne parvient pas à se connecter à un PC distant. Que faut-il vérifier ?
- Vérifiez d'abord que WinRM est configuré sur la machine cible. Une opération CIM avec -ComputerName crée une session temporaire via le protocole WSMan (WinRM), ce qui suppose que le service WinRM et son écouteur tournent bien sur la machine de destination. La commande winrm quickconfig effectue la configuration par défaut (démarrage du service, création de l'écouteur, exception de pare-feu). Les ports par défaut sont 5985 en HTTP et 5986 en HTTPS : vérifiez donc aussi le pare-feu sur le chemin réseau. Dans un environnement de groupe de travail, l'authentification mutuelle Kerberos n'est pas disponible, ce qui peut nécessiter d'inscrire la machine dans les TrustedHosts côté client. Si WinRM ne peut vraiment pas être configuré sur la machine cible, une autre solution consiste à se connecter en DCOM à l'aide d'une option créée avec New-CimSessionOption -Protocol Dcom.
- Pourquoi les dates WMI sont-elles renvoyées dans un format comme « 20260801100000.000000+540 » ?
- Parce que les dates WMI sont stockées sous forme de chaîne dans le format défini par la spécification CIM du DMTF (yyyymmddHHMMSS.mmmmmm±UUU, le suffixe étant le décalage en minutes par rapport à l'UTC). Lorsqu'on lit la valeur brute avec l'ancien Get-WmiObject ou avec System.Management, c'est cette chaîne telle quelle qui est renvoyée. En C# (System.Management), ManagementDateTimeConverter fournit des méthodes de conversion entre le format DMTF et DateTime / TimeSpan : utilisez-les plutôt que de découper la chaîne vous-même. À noter que lorsqu'on récupère les données via une API de type CIM comme Get-CimInstance, les propriétés de date sont déjà converties en DateTime, et ce problème ne se pose donc pas.
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.