Utiliser WMI/CIM depuis C# et PowerShell — guide pratique d'inventaire matériel, de surveillance des processus et d'interrogations distantes
· Mis à jour le: · Go Komura · Windows, C#, .NET, PowerShell, WMI, CIM, Applications métier, Développement Windows
Historique des révisions (première version, publiée le 1 Aug 2026)
- Première publication
Citer cet article(DOI (archive enregistrée): 10.5281/zenodo.22175750)
Les DOI ci-dessous renvoient à des versions déjà archivées et peuvent différer du texte actuel. Pour citer le texte actuel, utilisez l’URL de cette page.
Go Komura (2026). Utiliser WMI/CIM depuis C# et PowerShell — guide pratique d'inventaire matériel, de surveillance des processus et d'interrogations distantes. KomuraSoft LLC. https://comcomponent.com/fr/blog/wmi-cim-practical-guide/
- DOI (archive enregistrée)
- 10.5281/zenodo.22175750
- DOI (dernière version enregistrée)
- 10.5281/zenodo.22175751
« Je veux afficher le numéro de série et le nom de modèle du PC. » « Je veux vérifier l’espace disque libre d’un serveur. » « Je veux détecter le démarrage d’un processus. » Dans les applications métier et les outils d’administration Windows, WMI/CIM est ce qui permet de traiter ce type d’informations par un mécanisme commun.
CIM est le modèle standard pour représenter les informations de gestion, et WMI est l’infrastructure de gestion Windows qui utilise cette norme. Les cmdlets CIM de PowerShell et les API C# sont les points d’entrée vers cette infrastructure.1
flowchart TB
accTitle: Exigences courantes et WMI/CIM
accDescr: Afficher le numéro de série et le nom de modèle, surveiller l'espace disque libre, détecter le démarrage des processus et interroger des PC distants sont des exigences courantes des applications métier dont la réponse standard est WMI, qui utilise la norme CIM pour représenter les informations de gestion
r1["Numéro de série et nom de modèle"] --> ans["WMI (infrastructure qui utilise la norme CIM)"]
r2["Surveillance de l'espace disque libre"] --> ans
r3["Détection du démarrage des processus"] --> ans
r4["Interrogation de PC distants"] --> ans
Figure 1 : WMI/CIM est la réponse standard à quatre exigences qui reviennent sans cesse dans les applications métier.
Ce qui prête à confusion, c’est qu’il y a plusieurs points d’entrée. Les résultats de recherche mélangent l’ancien Get-WmiObject et Get-CimInstance, et C# a à la fois System.Management et Microsoft.Management.Infrastructure. Les anciens cmdlets WMI fonctionnent encore sous Windows PowerShell 5.1, mais ils n’existent pas dans PowerShell 7.2
Cet article s’adresse aux développeurs C#/PowerShell qui implémentent la récupération d’informations matérielles, la surveillance des processus et l’interrogation de PC distants. L’ordre est le suivant : décider si WMI est l’outil adapté, l’essayer en PowerShell, vérifier les conditions de connexion, l’intégrer dans C#, puis compléter par la surveillance et le diagnostic. Les exemples et les précautions s’appuient sur des sources primaires à jour en août 2026.
1. D’abord la conclusion : choisir le point d’entrée selon l’usage et la cible
Écrivez le PowerShell nouveau avec les cmdlets CIM, et choisissez l’API C# selon l’usage. Cela dit, il n’est pas nécessaire de faire porter à WMI le travail qu’un mécanisme dédié couvre déjà.
| Décision ou tâche | Approche de base | Chapitre qui la traite |
|---|---|---|
| Décider s’il faut utiliser WMI | L’utiliser pour la récupération transversale d’informations et les interrogations distantes ; choisir un mécanisme dédié pour la configuration et la surveillance de performance à haute fréquence | Chapitre 2 |
| Décider quoi interroger | Choisir l’espace de noms, la classe et les propriétés, et restreindre la cible avec WQL. La valeur par défaut du quotidien est root/CIMV23 |
Chapitres 3 et 4 |
| Essayer en PowerShell | Lire avec Get-CimInstance et agir avec Invoke-CimMethod. Écrire le code nouveau côté CIM même lorsqu’il vise 5.12 |
Chapitre 4 |
| Étendre aux machines distantes | Prendre WSMan/WinRM comme base, et réutiliser une session CIM pour plusieurs opérations contre la même cible. Choisir DCOM lorsqu’il le faut34 | Chapitre 5 |
| Intégrer dans C# | Utiliser System.Management pour des interrogations locales rapides, et envisager l’API MI lorsque l’on intègre des interrogations distantes ou de la surveillance56 |
Chapitre 6 |
| Surveiller le démarrage des processus | Utiliser un abonnement aux événements, et concevoir aussi les privilèges, le désabonnement et la réinscription après une coupure78 | Chapitre 7 |
| Comprendre pourquoi c’est lent, pourquoi la valeur est fausse ou pourquoi une classe est introuvable | Isoler le volume et la fréquence des interrogations, le nombre de bits du fournisseur et la cohérence du référentiel | Chapitre 8 |
En particulier, pouvoir énumérer quelque chose et pouvoir s’abonner à ses événements sont deux choses distinctes. L’exemple d’abonnement à Win32_ProcessStartTrace s’exécute avec des privilèges d’administrateur.7 Et n’allez pas par habitude vers SELECT * ou vers un polling à intervalle court : restreignez le résultat aux informations nécessaires avec -Filter, -Property et -KeyOnly.3
Dans le diagramme, un trait continu marque une relation qui vaut toujours et un trait pointillé une relation conditionnelle (les conditions figurent dans l’explication de chaque relation sur la page de détail). La liste complète des relations (26 au total, avec preuve et niveau de certitude) et les définitions des concepts principaux sont rassemblées sur la page de détail de la carte des connaissances (en japonais). Données : JSON-LD / Turtle
2. Quand utiliser WMI/CIM et quand choisir un mécanisme dédié
WMI est excellent comme interface de lecture unifiée, mais ce n’est pas toujours la meilleure réponse. Voici les repères pratiques pour distinguer les deux cas.
| Ce que l’on veut faire | Mécanisme adapté | Pourquoi pas WMI |
|---|---|---|
| Récupérer des informations matérielles et la configuration de l’OS, et interroger à distance sans agent | WMI/CIM | C’est là que WMI est le plus fort. Plus unifié que d’appeler des API dédiées une à une |
| Lire et écrire la configuration de sa propre application | Lecture directe du Registre (Microsoft.Win32.Registry) ou un fichier de configuration |
Toucher le Registre via WMI est un détour, et cela entraîne le problème de bits de la section 8.2 |
| Surveillance de performance continue et à haute fréquence, comme l’utilisation du processeur | Compteurs de performance (System.Diagnostics.PerformanceCounter et similaires) |
Les compteurs existent précisément pour cela. Le polling WMI à intervalle court perd à la fois en charge et en précision |
| Appels ponctuels à une fonction de l’OS, et traitements qui exigent une faible latence | L’API Win32 (P/Invoke) | WMI porte le surcoût du passage par COM et un fournisseur |
| Énumération et contrôle locaux de processus que les privilèges du processus lui-même couvrent déjà | System.Diagnostics.Process |
C’est autonome dans la bibliothèque standard, donc moins de dépendances |
| Configurer des fonctions d’administration Windows telles que le pare-feu et le réseau | Cmdlets dédiés basés sur CIM comme Get-NetFirewallRule |
Des jeux de cmdlets organisés par tâche sont plus précis et plus sûrs que de chercher des classes WMI brutes |
| Détecter les modifications de fichiers et de dossiers | FileSystemWatcher |
Ne pas amener WMI dans un domaine qui a déjà une API dédiée |
Le principe de décision est simple : utiliser le mécanisme dédié là où il en existe un, et utiliser WMI/CIM pour les interrogations transversales et les interrogations distantes. La famille Get-NetFirewallRule du tableau est elle-même un ensemble de cmdlets construits au-dessus de CIM, ce que l’on peut décrire comme obtenir le bénéfice de WMI/CIM sans le toucher directement.
flowchart TB
accTitle: Le principe de décision
accDescr: Le principe de décision est d'utiliser le mécanisme dédié dans les domaines qui en ont un et d'utiliser WMI et CIM pour les interrogations transversales et distantes dans ceux qui n'en ont pas, tandis que les cmdlets dédiés basés sur CIM sont une façon d'obtenir le bénéfice sans toucher WMI et CIM directement
q1{"Y a-t-il un mécanisme dédié ?"} -->|Oui| ded["Utiliser le mécanisme dédié"]
q1 -->|Non| wmi["Utiliser WMI / CIM"]
wmi -.-> use["Interrogations transversales et distantes"]
cmd["Cmdlets dédiés basés sur CIM"] -.-> ben["N'obtenir que le bénéfice"]
Figure 2 : Utiliser le mécanisme dédié là où il existe, et WMI/CIM pour les interrogations transversales et distantes.
3. Clarifier le mécanisme : la norme, les espaces de noms, les classes et WQL
3.1. CIM est la norme, WMI l’implémentation sur Windows
D’abord, une fois pour toutes, ranger les relations entre les termes.
| Terme | Ce que c’est réellement |
|---|---|
| CIM (Common Information Model) | Le modèle standard de l’industrie pour représenter les cibles de gestion telles que les systèmes, les applications, les réseaux et les périphériques. Défini et maintenu par le DMTF (Distributed Management Task Force)1 |
| WBEM (Web-Based Enterprise Management) | Une initiative de l’industrie qui crée des technologies standard pour accéder aux informations de gestion dans les environnements d’entreprise1 |
| WMI | L’implémentation Microsoft de WBEM. Elle utilise la norme CIM pour représenter les cibles de gestion et est intégrée à Windows1 |
| MI (Windows Management Infrastructure) | La version de nouvelle génération de WMI. Entièrement compatible avec le WMI classique, et la plupart des nouveaux fournisseurs sont écrits pour MI1 |
flowchart TB
accTitle: Relation entre la norme CIM et l'implémentation WMI
accDescr: La norme CIM définie et maintenue par le DMTF est utilisée dans le cadre de l'initiative WBEM, WMI en est l'implémentation Microsoft, la nouvelle génération MI est entièrement compatible avec le WMI classique, et les API de la famille CIM se connectent toutes à la même infrastructure WMI
dmtf["Défini et maintenu par le DMTF"] --> cim["CIM (modèle standard de l'industrie)"]
wbem["WBEM (initiative de l'industrie)"] --> wmi["WMI (implémentation Microsoft)"]
cim --> wmi
wmi -.-> mi["MI (nouvelle génération, entièrement compatible)"]
api["API de la famille CIM (PowerShell / C#)"] --> wmi
Figure 3 : CIM est la spécification et WMI l’implémentation sur Windows. Les API de la famille CIM se connectent toutes à la même infrastructure WMI.
3.2. Lire espaces de noms, classes, fournisseurs et WQL comme une seule chaîne
En tant que développeur, quatre éléments de structure doivent être clairs.
- Espace de noms (namespace) : une hiérarchie qui regroupe les classes. Les interrogations du quotidien utilisent presque toujours root/CIMV2, qui est aussi la valeur par défaut des cmdlets CIM.3 Il en existe d’autres, comme
root\default(le fournisseur du Registre, etc.). - Classe : un type de cible de gestion, comme
Win32_ComputerSystem(l’ordinateur lui-même),Win32_LogicalDisk(un lecteur logique) ouWin32_Process(un processus). Les classes propres à Windows qui dérivent des classes de la norme CIM (CIM_LogicalDisket similaires) portent le préfixeWin32_.9 - Fournisseur : le composant qui fournit les instances réelles d’une classe. Lorsque vous émettez une interrogation, le fournisseur interroge l’OS sur place et produit les valeurs.
- WQL : un langage d’interrogation proche du SQL. On traite une classe comme une table et on restreint, comme dans
SELECT Name, State FROM Win32_Service WHERE StartMode = 'Auto'. WQL est aussi le langage d’interrogation par défaut des cmdlets CIM.3
Pouvoir lire les informations de l’OS et du matériel à travers un ensemble unifié de classes et un langage d’interrogation : voilà la valeur de WMI. Toutes les classes ne prennent toutefois pas en charge l’écriture ni les opérations. Les classes qui ont des méthodes s’actionnent avec Invoke-CimMethod, et les modifications de propriétés inscriptibles se font avec Set-CimInstance. Comme le montre le tableau de correspondance de la section 4.1, on choisit le point d’entrée selon ce que la classe offre.
flowchart TB
accTitle: La structure d'une interrogation WMI
accDescr: Une interrogation WQL vise une classe Win32 dans l'espace de noms root/CIMV2, le fournisseur qui fournit les instances réelles de la classe interroge l'OS sur place et produit les valeurs, et le résultat est renvoyé
wql["Interroger avec WQL"] --> ns["Espace de noms root/CIMV2"]
ns --> cls["Classe Win32_*"]
cls --> prov["Fournisseur"]
prov --> osq["Interroge l'OS sur place"]
osq --> res["Renvoie le résultat"]
Figure 4 : Une interrogation suit l’espace de noms, puis la classe, puis le fournisseur, et les valeurs sont produites sur place.
4. Essayer en PowerShell : lecture, appel de méthodes et informations d’actifs
À partir d’ici, essayez sous PowerShell sur Windows. Même en portant d’ancien code, commencez par confirmer la correspondance des cmdlets et la différence de traitement des valeurs de retour.
4.1. Écrire le code nouveau avec les cmdlets CIM
Dans PowerShell 6 et versions ultérieures (le PowerShell 7 actuel), les cmdlets WMI v1 suivants ont été retirés. Les mêmes fonctionnalités sont fournies par le module CimCmdlets (WMI v2).2
| Ancien (jusqu’à Windows PowerShell 5.1) | Actuel (cmdlets CIM) | Remarques |
|---|---|---|
Get-WmiObject |
Get-CimInstance |
L’idée derrière -Filter / -Query est la même |
Get-WmiObject -List |
Get-CimClass |
Découvrir les classes et vérifier leurs définitions |
Invoke-WmiMethod |
Invoke-CimMethod |
Les arguments se passent en table de hachage avec -Arguments @{ } |
Register-WmiEvent |
Register-CimIndicationEvent |
Abonnement aux événements (chapitre 7) |
Set-WmiInstance |
Set-CimInstance |
Modifier des propriétés inscriptibles |
Remove-WmiObject |
Remove-CimInstance |
Supprimer une instance |
Les cmdlets CIM fonctionnent aussi sous Windows PowerShell 5.1, donc écrire tout ce qui est nouveau côté CIM, même lorsqu’il doit tourner sous 5.1, est la façon d’éviter de laisser un coût de migration. Le panorama de la coexistence de 5.1 et 7 et de la migration figure dans « Les différences entre Windows PowerShell 5.1 et PowerShell 7 ».
flowchart TB
accTitle: Pourquoi les scripts nouveaux doivent s'écrire avec CIM
accDescr: Un script écrit avec les cmdlets WMI s'exécute sous 5.1 mais a été retiré à partir de PowerShell 6, donc il faut le réécrire à la migration, tandis que les cmdlets CIM fonctionnent aussi sous 5.1, de sorte qu'écrire tout ce qui est nouveau côté CIM ne laisse aucun coût de migration
new["Un script nouveau"] --> q1{"Avec quoi l'écrire ?"}
q1 -->|Cmdlets WMI| old["S'exécute sous 5.1"]
q1 -->|Cmdlets CIM| cur["Fonctionne aussi sous 5.1"]
old --> del["Retiré dans PowerShell 7"]
del --> rew["Réécrire à la migration"]
cur --> norew["Aucun coût de migration laissé"]
Figure 5 : Écrire le code nouveau avec les cmdlets CIM et il n’y aura pas à le réécrire lors de la migration vers PowerShell 7.
4.2. Restreindre les lignes et les colonnes avec Get-CimInstance
# Spécifier la classe (espace de noms par défaut root/CIMV2)
Get-CimInstance -ClassName Win32_OperatingSystem
# Ne mettre que la clause WHERE dans -Filter (ne pas écrire 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
# Utiliser -Query si l'on veut écrire le WQL soi-même
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name LIKE 'p%'"
-Filter est la clause WHERE de WQL elle-même, 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 (CreationDate, LastBootUpTime, etc.) reviennent déjà converties en DateTime.
4.3. Appeler les méthodes avec Invoke-CimMethod
Contrairement à l’ancien Get-WmiObject, on n’appelle pas les méthodes WMI directement sur l’objet récupéré, donc les appels de méthodes passent par Invoke-CimMethod.
flowchart TB
accTitle: Appel d'une méthode sur une CimInstance
accDescr: La CimInstance renvoyée par Get-CimInstance revient avec les propriétés de date déjà converties en DateTime, mais ce n'est pas une forme sur laquelle on appelle les méthodes WMI directement, donc un appel de méthode se fait en passant l'instance à Invoke-CimMethod
gci["Get-CimInstance"] --> inst["Objet CimInstance"]
inst -.-> dt["Dates déjà converties en DateTime"]
inst -.-> nom["Les méthodes WMI passent par un autre point d'entrée"]
inst --> icm["La passer à Invoke-CimMethod"]
icm --> call["Appel de méthode"]
Figure 6 : N’appelez pas directement les méthodes WMI d’une CimInstance ; faites les appels de méthodes en passant l’instance à Invoke-CimMethod.
# Appeler une méthode sur une instance : obtenir 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 (la liste des propriétés et des méthodes)
Get-CimClass -ClassName Win32_Process
4.4. Choisir la classe d’après l’information voulue
| Information voulue | Classe | Propriétés principales |
|---|---|---|
| Fabricant et nom de modèle | Win32_ComputerSystem |
Manufacturer, Model |
| Numéro de série du châssis | Win32_BIOS |
SerialNumber |
| Édition de l’OS et 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 |
4.5. Un exemple de gestion d’actifs : modèle, numéro de série et espace disque libre
# Informations de modèle et numéro de série (pour rapprocher un registre d'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 est la valeur qui signifie « disque local », et elle exclut les lecteurs amovibles (2), les lecteurs réseau (4) et les CD (5).9 Une fois les conditions de connexion du chapitre 5 satisfaites, faire tourner ce script contre chaque serveur via une session CIM donne la base d’une surveillance de disque sans agent.
flowchart TB
accTitle: La base d'une surveillance de disque sans agent
accDescr: Filtrer sur DriveType 3 exclut les lecteurs amovibles, les lecteurs réseau et les CD de sorte que seuls les disques locaux sont couverts, et faire tourner le même script contre chaque serveur via une session CIM donne la base d'une surveillance de disque sans agent
scr["Script de récupération de l'espace libre"] --> flt["Filtrer sur DriveType = 3"]
flt -.-> exc["Exclut les lecteurs amovibles et similaires"]
scr --> ses["Via une session CIM"]
ses --> srvs["L'exécuter contre chaque serveur"]
srvs --> mon["Surveillance sans agent"]
Figure 7 : Faire tourner un script restreint aux disques locaux contre chaque serveur via une session CIM est la base de la surveillance.
5. Étendre aux machines distantes : modes de connexion et prérequis
5.1. Le mode de connexion change entre le local et le distant
Un cmdlet CIM auquel on ne passe pas -CimSession se connecte au WMI local via COM si -ComputerName n’est pas spécifié non plus, et crée une session temporaire via le protocole WSMan (WinRM) lorsque -ComputerName est spécifié. Si vous effectuez plusieurs opérations contre le même ordinateur, créer une session CIM et la réutiliser est plus performant.3
flowchart TB
accTitle: Choisir un mode de connexion CIM
accDescr: Sans CimSession, omettre ComputerName se connecte au WMI local via COM tandis que spécifier ComputerName crée une session WSMan temporaire à chaque interrogation, réutiliser New-CimSession est plus performant pour plusieurs opérations contre la même cible, et une option de protocole DCOM est disponible pour les cibles où WinRM n'est pas configuré
exec["Exécuter sans passer CimSession"] --> q1{"ComputerName est-il spécifié ?"}
q1 -->|Non| local["Connexion COM au WMI local"]
q1 -->|Oui| q2{"Plusieurs opérations sur la même cible ?"}
q2 -->|Ponctuel| temp["Session WSMan temporaire"]
q2 -->|Plusieurs| sess["Réutiliser New-CimSession"]
temp -.-> cost["Créée à chaque interrogation"]
nowinrm["Cible sans WinRM configuré"] -.-> dcom["Option de protocole DCOM"]
Figure 8 : Les interrogations distantes passent par WSMan par défaut, et réutiliser une session CIM est la pratique établie pour plusieurs opérations contre la même cible.
5.2. Préparer WinRM, le pare-feu, l’authentification et les privilèges
Les prérequis pour interroger via WSMan/WinRM sont les suivants. Avant d’écrire le moindre code de connexion, vérifiez séparément le service, le chemin réseau, l’authentification et les privilèges.
- WinRM doit être configuré sur la cible.
winrm quickconfigfait tout d’un coup : mettre le service en démarrage automatique, créer un écouteur HTTP (port par défaut 5985) et enregistrer une exception de pare-feu.10 Si vous voulez vous 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 - Les ports concernés doivent être ouverts dans les pare-feu sur le chemin. Concevoir et enregistrer des règles entrantes en pratique fonctionne exactement comme dans l’article sur le pare-feu Windows et les applications métier.
- Authentification. Dans un environnement de domaine, Kerberos fournit l’authentification mutuelle. Kerberos n’est pas disponible dans un groupe de travail, ce qui peut exiger d’inscrire la cible dans la liste
TrustedHostsdu client. Tenez cette liste au strict minimum.10 - Privilèges. Avec la configuration par défaut, les interrogations et opérations WMI distantes se font normalement avec un compte qui appartient au groupe des administrateurs sur la cible. Si vous voulez l’ouvrir aux utilisateurs standard, il faut configurer les autorisations d’accès à la fois dans WinRM et dans l’espace de noms WMI.10
flowchart TB
accTitle: Vérifier les prérequis des interrogations distantes
accDescr: Sur la cible, winrm quickconfig met le service en démarrage automatique, crée un écouteur HTTP et enregistre une exception de pare-feu d'un coup, un écouteur HTTPS se configure séparément après préparation d'un certificat, et dans un groupe de travail l'inscription dans TrustedHosts peut être exigée
qc["winrm quickconfig"] --> svc["Service mis en démarrage automatique"]
qc --> lis["Écouteur HTTP créé (5985)"]
qc --> fw["Exception de pare-feu"]
lis ~~~ https["Écouteur HTTPS (5986)"]
https -.-> cert["Préparer un certificat et configurer séparément"]
fw ~~~ wg["Environnement de groupe de travail"]
wg -.-> th["N'inscrire que là où c'est nécessaire"]
Figure 9 : winrm quickconfig applique la configuration par défaut en une étape ; l’écouteur HTTPS et l’authentification en groupe de travail se traitent à part.
5.3. Réutiliser une session CIM pour plusieurs opérations contre la même cible
# Pour une opération ponctuelle, utiliser -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
5.4. Envisager DCOM pour les cibles où WinRM ne peut pas être configuré
Pour les cibles que vous ne pouvez pas atteindre via WSMan, par exemple des machines anciennes où WinRM ne peut pas être configuré, vous pouvez choisir le protocole DCOM.4
$dcom = New-CimSessionOption -Protocol Dcom
$session = New-CimSession -ComputerName OldServer -SessionOption $dcom
DCOM utilise aussi des ports RPC dynamiques, ce qui rend plus difficile la conception de tout ce qui traverse un pare-feu. Pour tout ce que vous construisez maintenant, traiter WSMan comme valeur par défaut est l’hypothèse la plus sûre.
Les exemples de session montrent comment se connecter. Lors de l’intégration, garantissez le nettoyage avec try / finally ou équivalent afin que Remove-CimSession soit atteint même si une interrogation échoue en cours de route. La session créée dans l’exemple DCOM se libère de la même façon.
6. Intégrer dans C# : deux API et le traitement des types et des dates
6.1. Choisir entre les deux API selon l’usage
Il existe deux lignées d’API pour utiliser WMI depuis C#. Les deux sont réservées à Windows.
| System.Management | Microsoft.Management.Infrastructure (API MI) | |
|---|---|---|
| Comment l’obtenir | Intégré à .NET Framework. Sur le .NET actuel, le paquet NuGet System.Management5 | Le paquet NuGet Microsoft.Management.Infrastructure6 |
| Classe d’entrée | ManagementObjectSearcher (lui passer du WQL pour interroger)5 |
CimSession (Create, puis QueryInstances / InvokeMethod / Subscribe)6 |
| Système de types | ManagementObject / ManagementEventWatcher11 |
CimInstance / CimSession — les mêmes types que les cmdlets CIM3 |
| Distant | Basé sur DCOM | Basé sur WSMan (sessions CIM). Variantes asynchrones (*Async) disponibles6 |
| Là où cela convient | Récupération d’informations locales. Maintenir une base de code existante | Intégrer des interrogations distantes et de la surveillance. Conceptions qui utilisent aussi PowerShell |
6.2. System.Management : lui passer du WQL et lire selon les types CIM
Passez le WQL sous forme de chaîne et recevez la collection de résultats depuis Get().5
// NuGet: System.Management (Windows uniquement)
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} GB / total {sizeGb:F1} GB");
}
Les propriétés reviennent via l’indexeur comme object, donc vérifiez le type CIM dans la documentation de la classe (ici FreeSpace et Size sont uint649) et convertissez en conséquence. Convertir en int parce que l’on a supposé que c’était le type, sans vérifier, donne une InvalidCastException : c’est le premier faux pas classique.
flowchart TB
accTitle: Récupération des propriétés et piège de la conversion
accDescr: Les propriétés System.Management reviennent via l'indexeur comme object, donc il faut vérifier le type CIM dans la documentation de la classe avant de convertir, et convertir en supposant que c'est un int donne une InvalidCastException
idx["Récupéré via l'indexeur"] --> obj["Revient comme object"]
obj --> chk["Vérifier le type CIM dans la documentation"]
chk --> cast["Convertir vers le type correct"]
obj -.-> wrong["Convertir en supposant que c'est un int"]
wrong -.-> ex["InvalidCastException"]
Figure 10 : Les propriétés reviennent comme object, donc vérifiez le type CIM avant de convertir.
6.3. L’API MI : interroger avec les mêmes types que PowerShell
CimSession traite le local et le distant de la même façon. L’énumération, les interrogations, les appels de méthodes, l’abonnement aux événements et les variantes asynchrones sont tous là.6
// NuGet: Microsoft.Management.Infrastructure (Windows uniquement)
using Microsoft.Management.Infrastructure;
// CimSession.Create(null) pour le local ; passer un nom d'ordinateur pour le distant
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} GB");
}
Parce que vous manipulez le même CimInstance que celui que renvoient les cmdlets CIM de PowerShell, le flux de développement « essayer en PowerShell, puis transcrire dans C# » s’enchaîne naturellement. Si vous concevez l’intégration C#–PowerShell elle-même, voir aussi « Comment exécuter PowerShell depuis C# et récupérer le résultat sous forme d’objets ».
flowchart TB
accTitle: Prototyper en PowerShell et transcrire dans C#
accDescr: Parce que les cmdlets CIM de PowerShell et l'API MI de C# manipulent le même type CimInstance, le flux de développement qui consiste à prototyper en PowerShell puis à transcrire dans C# s'enchaîne naturellement
trial["Prototyper en PowerShell"] --> gci["Cmdlets CIM"]
impl["Implémentation réelle en C#"] --> mi["API MI"]
gci --> ci["Le même type CimInstance"]
mi --> ci
ci -.-> flow["La transcription s'enchaîne naturellement"]
Figure 11 : Les cmdlets CIM et l’API MI manipulent le même type CimInstance, donc un prototype se reporte dans l’implémentation réelle.
6.4. Ne pas découper les dates DMTF à la main ; les passer à l’API de conversion
Les dates WMI sont stockées comme chaînes au format DMTF de la spécification CIM, yyyymmddHHMMSS.mmmmmm±UUU (la valeur finale est le décalage par rapport à l’UTC en minutes ; par exemple 20260801100000.000000+540). Arrêtez de découper la valeur brute par des opérations sur chaînes et utilisez une API de conversion.
- C# (System.Management) :
ManagementDateTimeConverterfournit la conversion dans les deux sens entre le format DMTF etDateTime/TimeSpan.11 - API de la famille CIM (Get-CimInstance / l’API MI) : les propriétés de date reviennent déjà converties en
DateTime, donc vous ne rencontrez pas le problème.(Get-CimInstance Win32_OperatingSystem).LastBootUpTimepeut s’utiliser directement commeDateTimedans un calcul.
flowchart TB
accTitle: Traitement du format de date DMTF
accDescr: Les dates WMI sont stockées comme chaînes au format DMTF, donc une valeur brute lue via System.Management se convertit avec ManagementDateTimeConverter tandis qu'une API de la famille CIM la renvoie déjà convertie en DateTime, et l'on ne découpe jamais la chaîne soi-même
dmtf["Chaîne au format DMTF"] --> q1{"Quelle API l'a récupérée ?"}
q1 -->|System.Management| conv["ManagementDateTimeConverter"]
q1 -->|API de la famille CIM| done["Renvoyée déjà convertie en DateTime"]
conv --> dtv["Convertir en DateTime / TimeSpan"]
cut["Découper la chaîne soi-même"] -.-> ng["Ne pas faire cela"]
Figure 12 : Laisser la conversion de la chaîne DMTF à l’API de conversion, et avec une API de la famille CIM utiliser simplement le DateTime fourni.
Le code ici montre la forme de base de chaque API. Dans une application réelle, il faut aussi traiter les échecs de récupération et les valeurs non définies, et disposer les collections de résultats, les objets récupérés et les sessions de la façon qu’exige l’API utilisée.
7. Surveiller le démarrage des processus : privilèges, abonnement, désabonnement et réinscription
Plutôt que de « interroger Win32_Process à intervalles et comparer les différences », utilisez un abonnement aux événements. Pour le démarrage des processus, l’approche la plus simple est de s’abonner à Win32_ProcessStartTrace (une classe d’événement du fournisseur de trace du noyau, avec des propriétés telles que ProcessName, ProcessID et ParentProcessID8).
7.1. Décider d’abord les privilèges d’exécution et l’endroit où vit la surveillance
Register-CimIndicationEvent enregistre un abonnement par nom de classe ou requête d’événement WQL, et le bloc de script dans -Action s’exécute à chaque arrivée d’une indication.7 S’abonner à cette classe exige des privilèges d’administrateur.7 Qui peut recevoir un événement est contrôlé par le descripteur de sécurité de la classe d’événement, et un utilisateur standard reçoit un accès refusé.8
Les abonnements à la famille Win32_ProcessStartTrace supposent des privilèges d’administrateur.7 « Cela marchait sur la machine de développement, où l’on s’exécutait en administrateur, mais la surveillance ne fonctionne pas dans l’environnement utilisateur standard du client » est un échec aussi classique que la boîte de dialogue de notification du pare-feu. Si vous intégrez une surveillance dans une application métier qui s’exécute en utilisateur standard, envisagez de séparer la partie surveillance dans un service Windows (s’exécutant comme LocalSystem ou similaire) et de la relier à l’application elle-même par communication interprocessus.
flowchart TB
accTitle: Une disposition de surveillance pour les environnements utilisateur standard
accDescr: Un abonnement qui exige des privilèges d'administrateur est extrait de l'application elle-même qui s'exécute en utilisateur standard, la partie surveillance est séparée dans un service Windows s'exécutant comme LocalSystem ou similaire, et les deux sont reliés par communication interprocessus
svcm["Service Windows de surveillance"] --> subm["S'abonne à la trace de démarrage"]
svcm -.-> lsm["S'exécute comme LocalSystem ou similaire"]
appm["L'application elle-même (utilisateur standard)"] ---|Communication interprocessus| svcm
Figure 13 : Séparer un abonnement qui exige des privilèges d’administrateur du côté service et le relier à l’application par communication interprocessus.
7.2. S’abonner en PowerShell et se désabonner lorsque la surveillance se termine
# Exécuter ceci dans une session PowerShell élevée
$action = {
$name = $Event.SourceEventArgs.NewEvent.ProcessName
$id = $Event.SourceEventArgs.NewEvent.ProcessID
Write-Host "Processus démarré : $name (PID=$id)"
}
Register-CimIndicationEvent -ClassName Win32_ProcessStartTrace `
-SourceIdentifier ProcessStarted -Action $action
L’abonnement est lié à la session PowerShell qui l’a enregistré, et tant qu’elle continue de tourner normalement, -Action s’exécute à chaque démarrage de processus. Attention à ne pas enchaîner tout de suite la commande de désabonnement d’un seul trait : cela ne fait que retirer l’abonnement avant même que la surveillance ne commence.
Se désabonner lorsque vous avez fini de surveiller.
# Lorsque la surveillance se termine : retirer l'abonnement
Unregister-Event -SourceIdentifier ProcessStarted
sequenceDiagram
accTitle: Le flux d'un abonnement à l'événement de démarrage de processus
accDescr: Une session PowerShell élevée enregistre un abonnement avec Register-CimIndicationEvent, un événement arrive à chaque démarrage de processus et Action s'exécute, et l'abonnement est retiré avec Unregister-Event lorsque la surveillance se termine
participant ps as Session PowerShell
participant wmi as WMI
ps->>wmi: Enregistrer l'abonnement avec Register-CimIndicationEvent
Note over ps: Exécuter avec des privilèges d'administrateur
wmi-->>ps: Un événement arrive à chaque démarrage de processus
ps->>ps: Exécuter -Action
ps->>wmi: Le retirer avec Unregister-Event (lorsque la surveillance se termine)
Figure 14 : Un abonnement est lié à la session qui l’a enregistré, et l’on se désabonne lorsque la surveillance se termine.
7.3. L’événement générique qui utilise WITHIN est du polling
L’autre approche est l’événement de création d’instance générique (__InstanceCreationEvent), qui surveille la création d’instances d’une classe. Ici WMI interroge à l’intervalle que vous donnez avec WITHIN et transforme les différences en événements, donc le compromis entre latence de détection et charge vous appartient.
flowchart TB
accTitle: Deux méthodes d'abonnement pour détecter le démarrage des processus
accDescr: Win32_ProcessStartTrace est une méthode qui s'abonne à une classe d'événement du fournisseur de trace du noyau, tandis que le __InstanceCreationEvent générique fait interroger WMI à l'intervalle donné avec WITHIN et transformer les différences en événements, donc le compromis entre latence de détection et charge vous appartient
goal["Détecter le démarrage des processus"] --> t1["Win32_ProcessStartTrace"]
goal --> t2["__InstanceCreationEvent"]
t1 -.-> k1["S'abonner à une trace du noyau"]
t2 -.-> w1["Interroge à l'intervalle WITHIN"]
w1 -.-> tr["Compromis entre intervalle et charge"]
Figure 15 : Soit s’abonner à une classe d’événement dédiée, soit utiliser l’événement générique de création d’instance avec un intervalle de polling.
# Surveiller les nouvelles instances de Win32_Process par polling à intervalles de 5 secondes
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier ProcPoll -Action {
Write-Host "Démarré : $($Event.SourceEventArgs.NewEvent.TargetInstance.Name)"
}
7.4. En C#, recevoir les événements avec ManagementEventWatcher
En C# (System.Management), ManagementEventWatcher joue le même rôle.11
using System.Management;
// Dans un processus s'exécutant en 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($"Processus démarré : {name} (PID={pid})");
};
watcher.Start();
// Lorsque la surveillance se termine, ne pas oublier watcher.Stop() et Dispose
7.5. Pour une surveillance permanente, concevoir la réinscription après la chute d’un abonnement
Lorsque vous intégrez cela dans une surveillance permanente, incluez dans la conception la réinscription après la chute de l’abonnement (au redémarrage du service, ou après une erreur). La réflexion de conception derrière « vérifier et afficher l’état », y compris la surveillance de périphériques, est traitée dans « Bonnes pratiques pour vérifier et afficher l’état des équipements externes ».
stateDiagram-v2
accTitle: Le cycle de vie de l'abonnement dans une surveillance permanente
accDescr: Dans une surveillance permanente l'état abonné peut chuter au redémarrage d'un service ou sur une erreur, donc la conception doit inclure la détection de cette chute, la réinscription et le retour à l'état abonné
s1: Abonné
s2: Abonnement tombé
s3: Réinscrire
[*] --> s1
s1 --> s2: Redémarrage du service ou erreur
s2 --> s3
s3 --> s1
Figure 16 : Une surveillance permanente doit inclure la conception pour se réinscrire et revenir à l’état abonné lorsqu’un abonnement chute.
8. Isoler les défaillances : performance, bits et référentiel
Si vous ne pouvez pas vous connecter, revenez à la section 5.2 ; si seul l’abonnement est refusé, section 7.1 ; pour la conversion et le traitement des dates, sections 6.2 et 6.4. Cette section sépare les autres cas fréquents : « lent », « mauvaise valeur » et « classe introuvable ».
8.1. Lent : revoir la quantité récupérée, la fréquence et les sessions
Une interrogation WMI est un travail dans lequel « le fournisseur produit les valeurs sur place », et ce n’est pas gratuit. Il y a deux anti-modèles classiques.
- Aller vers
SELECT *par habitude. Récupérer toutes les instances deWin32_Processavec toutes les propriétés gonfle à la fois le travail du fournisseur et, pour les interrogations distantes, le transfert réseau. Restreignez les lignes avec-Filteret les colonnes avec-Property, et utilisez-KeyOnlysi vous ne voulez que les clés pour une opération suivante. Ce sont tous des moyens officiellement fournis pour « réduire la taille des objets et le trafic réseau ».3 - Polling à intervalle court. Une conception du type «
Get-CimInstance Win32_Processune fois par seconde » doit être remplacée par l’abonnement aux événements du chapitre 7. Même lorsque vous devez vraiment utiliser la forme de polling (WITHIN), élargissez l’intervalle jusqu’au plus petit qui satisfait encore l’exigence.
Répéter -ComputerName machine par machine contre des cibles distantes est aussi assez gaspilleur. Une session temporaire est créée à chaque interrogation, donc faites passer plusieurs opérations à la réutilisation d’une session CIM.3
flowchart TB
accTitle: Anti-modèles de performance et par quoi les remplacer
accDescr: Aller vers SELECT astérisque par habitude se remplace par restreindre les lignes et les colonnes avec Filter et Property et utiliser KeyOnly lorsque seules les clés sont nécessaires, le polling à intervalle court se remplace par un abonnement aux événements, et répéter ComputerName machine par machine se remplace par réutiliser une session CIM
a1["Aller vers SELECT * par habitude"] --> f1["Restreindre avec Filter et Property"]
f1 -.-> f2["KeyOnly si vous ne voulez que les clés"]
a2["Polling à intervalle court"] --> f3["Remplacer par un abonnement aux événements"]
a3["ComputerName machine par machine"] --> f4["Réutiliser une session CIM"]
Figure 17 : Restreindre les lignes, les colonnes et les clés, la bonne méthode de surveillance et la réutilisation de session maintiennent la charge inutile à bas niveau.
8.2. Mauvaise valeur : vérifier les fournisseurs 32 bits et 64 bits
Sous Windows 64 bits, certains fournisseurs existent à la fois en versions 32 bits et 64 bits, et par défaut c’est celui qui correspond au nombre de bits de l’application appelante qui répond.12 Le cas classique est le fournisseur du Registre (StdRegProv) dans root\default : lisez-le depuis une application 32 bits et vous obtenez les valeurs du côté Wow6432Node (la vue 32 bits).12 Lorsque « la valeur de Registre lue via WMI est différente de ce que montre regedit », soupçonnez d’abord cela.
Si vous avez besoin de l’autre vue, vous pouvez la demander explicitement en spécifiant __ProviderArchitecture dans le contexte à la connexion (plus __RequiredArchitecture si vous voulez la rendre obligatoire).12 Le panorama du problème de bits est aussi traité dans « Appeler les API Win32 en toute sécurité depuis C# — guide pratique de P/Invoke ».
flowchart TB
accTitle: Choix du fournisseur dans un environnement 64 bits
accDescr: Par défaut le fournisseur correspondant au nombre de bits de l'application appelante répond, donc une interrogation du Registre depuis une application 32 bits reçoit les valeurs du côté Wow6432Node, mais spécifier __ProviderArchitecture permet de demander explicitement l'autre vue
q1{"Quel est le nombre de bits de l'appelant ?"} -->|32 bits| p32["Le fournisseur 32 bits répond"]
q1 -->|64 bits| p64["Le fournisseur 64 bits répond"]
p32 -.-> wow["Les valeurs du Registre viennent de Wow6432Node"]
ctx["Spécifier __ProviderArchitecture"] -.-> ov["Demander explicitement l'autre vue"]
Figure 18 : Par défaut le côté correspondant au nombre de bits de l’appelant répond, donc une application 32 bits lit le côté Wow6432Node.
8.3. Classe introuvable : vérifier le référentiel avant de le réparer
Les définitions de classes WMI sont stockées dans le référentiel (pas un fichier unique : l’ensemble des fichiers à l’intérieur du dossier Repository fonctionne comme base de données13). Lorsqu’il devient incohérent, des erreurs telles que « une classe qui devrait exister est introuvable » ou « espace de noms non valide » commencent à apparaître alors que rien n’a changé côté application.
Utilisez winmgmt.exe pour isoler et réparer.13
rem Vérification de cohérence (un résultat inconsistent signifie qu'il y a une incohérence)
winmgmt /verifyrepository
rem Vérification de cohérence plus reconstruction s'il y a une incohérence (le contenu lisible est fusionné)
winmgmt /salvagerepository
Ce qu’il faut surveiller, c’est de ne pas faire de la suppression ou de la réinitialisation du référentiel votre premier geste. Les erreurs qui affleurent via WMI peuvent avoir leur origine ailleurs dans l’OS, et Microsoft affirme explicitement que faire de la suppression du référentiel le premier remède « peut causer des dommages au système ou aux applications installées ».13 Tenez l’ordre : vérifier avec /verifyrepository, puis réparer avec /salvagerepository.
flowchart TB
accTitle: Isoler une incohérence du référentiel WMI
accDescr: Lorsque des erreurs telles qu'une classe introuvable apparaissent, vérifier la cohérence avec winmgmt verifyrepository, reconstruire avec salvagerepository si c'est incohérent, et ne jamais faire de la suppression ou de la réinitialisation du référentiel le premier geste
sym["Erreurs telles que classe introuvable"] --> verify["winmgmt /verifyrepository"]
verify --> q1{"Le résultat est-il inconsistent ?"}
q1 -->|Oui| salvage["winmgmt /salvagerepository"]
q1 -->|Non| other["Soupçonner une cause ailleurs dans l'OS"]
salvage -.-> merge["Le contenu lisible est fusionné"]
del["Supprimer ou réinitialiser le référentiel"] -.-> ng["Pas votre premier geste"]
Figure 19 : Tenez l’ordre de vérifier d’abord puis de salvager, et ne faites pas de la suppression votre premier geste.
9. Synthèse : relier les interrogations à la surveillance et à l’exploitation
WMI/CIM est un point d’entrée commun pour interroger transversalement les informations de gestion Windows. Ce n’est pas un outil pour tout faire passer par WMI, y compris le travail qu’une API dédiée couvre déjà.
| Étape de l’intégration | Ce qu’il faut vérifier |
|---|---|
| Choisir l’outil | Préférer un mécanisme dédié pour la configuration, la surveillance de performance à haute fréquence et les opérations ponctuelles de l’OS, et utiliser WMI/CIM pour la récupération d’informations et les interrogations distantes |
| Essayer en PowerShell | Écrire avec les cmdlets CIM même pour 5.1. Choisir une classe dans root/CIMV2 et restreindre les lignes, les colonnes et les clés |
| Étendre aux machines distantes | Mettre en place les conditions de connexion WSMan/WinRM, et réutiliser une session pour plusieurs opérations. Envisager l’option DCOM pour les cibles qui en ont besoin |
| Passer dans C# | Choisir entre System.Management, qui convient aux interrogations locales, et l’API MI, qui convient aux interrogations distantes et à la surveillance. Vérifier le traitement des types et des dates |
| En faire une surveillance permanente | Vérifier les privilèges qu’exige Win32_ProcessStartTrace, et concevoir l’abonnement, le désabonnement et la réinscription après une coupure comme un flux continu |
| Enquêter sur une défaillance | Isoler le polling à intervalle court, le nombre de bits du fournisseur et la cohérence du référentiel. Ne pas faire de la suppression le premier remède |
Une fois que l’on pense la norme CIM et l’implémentation WMI, les interrogations et les abonnements aux événements, et les connexions et les autorisations d’accès comme des choses distinctes, il devient clair quel outil choisir et quoi vérifier. Commencez par récupérer en PowerShell les informations nécessaires, puis portez ce résultat jusqu’à l’implémentation C# et à la conception d’exploitation.
Articles connexes
- Comment exécuter PowerShell depuis C# (CSharp) et récupérer le résultat sous forme d’objets
- Recueil de commandes PowerShell pratiques — enrichir les petits outils utilisés au quotidien
- Windows PowerShell 5.1 et PowerShell 7 : quelles différences ? — Guide pratique de migration des scripts internes
- Bonnes pratiques pour vérifier et afficher l’état des équipements externes - Concevoir au-delà d’un simple « Connecté »
- Appeler les API Win32 en toute sécurité depuis C# — Guide pratique de P/Invoke (DllImport / LibraryImport / CsWin32)
- Le TPM sous Windows expliqué en images — le « coffre-fort qui ne laisse jamais sortir la clé » et le démarrage mesuré
Domaines de conseil associés
Chez KomuraSoft LLC, nous prenons en charge l’intégration dans des applications métier de la récupération d’informations matérielles, de la surveillance des processus et des interrogations de PC distants basées sur WMI/CIM, la migration vers les cmdlets CIM de scripts internes construits sur Get-WmiObject, et l’investigation de la classe de problème où « cela fonctionne sur la machine de développement mais se heurte à une erreur de permissions chez le client ». Vous pouvez nous confier l’ensemble, du prototypage en PowerShell jusqu’à l’implémentation réelle en C#, comme un engagement continu.
- Développement d’applications Windows
- Investigation de bugs et analyse des causes
- Conseil technique et revue de conception
- Nous contacter
Références
-
Microsoft Learn, About WMI. Sur le fait que WMI est l’implémentation Microsoft de WBEM (une initiative de l’industrie qui développe des technologies standard pour accéder aux informations de gestion dans les environnements d’entreprise), sur son usage de la norme industrielle CIM (Common Information Model) pour représenter les cibles de gestion et sur le fait que CIM est développé et maintenu par le DMTF (Distributed Management Task Force), sur le fait que la nouvelle génération MI (Windows Management Infrastructure) est entièrement compatible avec le WMI classique, et sur le fait que les connexions WMI distantes se font via 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 le fait que les cmdlets WMI v1 (Register-WmiEvent / Set-WmiInstance / Invoke-WmiMethod / Get-WmiObject / Remove-WmiObject) ont été retirés de PowerShell, et sur le fait que les cmdlets du module CimCmdlets (WMI v2) fournissent les mêmes fonctionnalités avec de nouvelles capacités et une syntaxe repensée. ↩ ↩2 ↩3
-
Microsoft Learn, Get-CimInstance (CimCmdlets). Sur le fait que, sans ComputerName ni CimSession, la connexion au WMI local se fait par une session COM et que spécifier -ComputerName crée une session temporaire via le protocole WsMan, sur le fait qu’une connexion de session CIM est recommandée pour la performance lorsque l’on effectue plusieurs opérations contre le même ordinateur, sur le fait que -Filter est une clause where WQL/CQL qui n’inclut pas le mot-clé WHERE, sur le fait que -Property et -KeyOnly réduisent 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 dialecte d’interrogation par défaut (-QueryDialect) est WQL, sur le fait que la sortie est Microsoft.Management.Infrastructure.CimInstance, sur l’exemple d’appel GetOwner combiné à Invoke-CimMethod, et sur le fait que le cmdlet est réservé à Windows. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, New-CimSessionOption (CimCmdlets). Sur le fait que les options de session CIM ont deux jeux de paramètres, l’un pour WsMan et l’un pour DCOM, sur le fait que -Protocol accepte Dcom / Default / Wsman, sur l’exemple qui passe une option créée avec New-CimSessionOption -Protocol Dcom au paramètre -SessionOption de New-CimSession pour créer une session CIM 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, qui récupère une collection d’objets de gestion d’après une interrogation WQL spécifiée, sur le fait qu’elle prend un ObjectQuery et un ManagementScope (un espace de noms WMI) et renvoie un ManagementObjectCollection depuis Get(), et sur le fait que System.Management.dll est fourni comme le paquet NuGet System.Management. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, CimSession Class (Microsoft.Management.Infrastructure). Sur le fait que Microsoft.Management.Infrastructure.dll est fourni comme le paquet NuGet Microsoft.Management.Infrastructure, sur la création d’une session avec Create(computerName), sur l’exécution d’une interrogation avec QueryInstances(namespace, queryDialect, query), et sur le fait que la classe fournit EnumerateInstances / GetInstance / InvokeMethod / Subscribe ainsi que la variante asynchrone de chacun (*Async) et implémente IDisposable. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Register-CimIndicationEvent (CimCmdlets). Sur le fait de s’abonner à des indications (événements) par nom de classe ou expression de requête et de nommer l’abonnement avec -SourceIdentifier, sur l’exemple d’abonnement à Win32_ProcessStartTrace et la note selon laquelle l’exécuter exige de lancer PowerShell en administrateur, sur l’exemple qui référence ProcessName / ProcessId depuis $Event.SourceEventArgs.NewEvent dans le bloc de script -Action, sur le fait de créer une session WsMan temporaire lorsque -ComputerName est spécifié et de se connecter localement via COM lorsqu’il ne l’est pas, et sur l’utilisation d’Unregister-Event pour retirer un abonnement. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Win32_ProcessStartTrace class. Sur le fait qu’il s’agit d’une classe d’événement qui indique le démarrage d’un nouveau processus et qui a des propriétés telles que ProcessName / ProcessID / ParentProcessID / SessionID / Sid, sur le fait que la propriété SECURITY_DESCRIPTOR est le descripteur par lequel le fournisseur d’événements détermine quels utilisateurs peuvent recevoir l’événement, et sur le fait que la classe vit dans l’espace de noms Root\CIMV2 et est fournie 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 qui représente 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 uint64 en octets, sur le fait que DeviceID est la clé, et sur les exemples d’interrogation VBScript et C# qui filtrent avec DriveType = 3. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Installation and configuration for Windows Remote Management. Sur le fait qu’aucun écouteur WinRM n’est configuré par défaut de sorte que les messages WS-Management ne peuvent être ni envoyés ni reçus, sur le fait que winrm quickconfig met le service en démarrage automatique, configure des écouteurs HTTP/HTTPS et enregistre une exception de pare-feu, sur le fait que les ports par défaut de WinRM 2.0 sont HTTP 5985 / HTTPS 5986, sur le fait de régler TrustedHosts aussi étroitement que possible lorsque l’authentification mutuelle (Kerberos) ne peut pas s’établir, comme dans un groupe de travail, et sur le descripteur de sécurité par défaut (RootSDDL) qui contrôle l’accès distant à l’écouteur et la configuration supplémentaire exigée pour laisser des utilisateurs non administrateurs utiliser le plug-in WMI. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, System.Management Namespace. Sur le fait qu’il s’agit de l’espace de noms qui interroge l’infrastructure WMI via la famille de classes ManagementObjectSearcher et s’abonne aux événements avec ManagementEventWatcher, sur le fait que WqlEventQuery représente une interrogation d’événement sous forme WQL, et sur le fait que ManagementDateTimeConverter fournit des méthodes pour convertir entre les dates/heures et intervalles DMTF et DateTime / TimeSpan du CLR. ↩ ↩2 ↩3
-
Microsoft Learn, Requesting WMI Data on a 64-bit Platform. Sur le fait que le fournisseur 32 bits répond aux applications 32 bits (y compris les scripts) et le fournisseur 64 bits aux applications 64 bits par défaut lorsqu’il existe à la fois une version 32 bits et une version 64 bits d’un fournisseur, sur le fait que les valeurs de contexte __ProviderArchitecture (32 ou 64) et __RequiredArchitecture permettent de demander et d’imposer le fournisseur non par défaut (avec WBEM_E_PROVIDER_LOAD_FAILURE si la version demandée n’existe pas lorsqu’elle est imposée), et sur l’exemple du fournisseur du Registre dans lequel 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 référentiel WMI, sur le fait que /salvagerepository effectue une vérification de cohérence et reconstruit le référentiel lorsqu’une incohérence est détectée tout en fusionnant le contenu qu’il a pu lire, sur le fait que /resetrepository le ramène à l’état qu’il avait à l’installation initiale de l’OS, sur le fait que le référentiel est un ensemble de fichiers à l’intérieur du dossier Repository qui fonctionne comme base de données, et sur le fait que les erreurs qui affleurent via WMI ont parfois leur origine ailleurs dans l’OS, de sorte que supprimer le référentiel comme premier remède ne doit pas se faire car cela peut causer des dommages au système ou aux applications installées. ↩ ↩2 ↩3
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Pourquoi les arguments se cassent — Les règles des arguments de ligne de commande Windows
Windows passe à CreateProcess une seule chaîne que le destinataire découpe. Traite les règles de CommandLineToArgvW, du CRT et de .NET, A...
Fin de la maintenance des pilotes d'imprimante Windows — Comment les applications métier doivent préparer l'impression des rapports et des étiquettes
Microsoft met progressivement fin aux pilotes d'imprimante v3/v4. Ce que Windows protected print mode retire, et comment inventorier et p...
Ère japonaise, jours fériés et dates de clôture dans les applications métier — conception résiliente aux changements d'ère, JapaneseCalendar et calcul des jours ouvrés en pratique
Afficher « Reiwa 8 » sur un bordereau, calculer des jours ouvrés en excluant les jours fériés, régler un paiement à la fin du mois suivan...
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...
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...
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 pour représenter les cibles de gestion telles que les systèmes et les périphériques, défini et maintenu par le DMTF (Distributed Management Task Force). WMI est l'implémentation Microsoft de WBEM, une initiative qui utilise cette norme, et il est intégré à Windows. Autrement dit, CIM est la spécification et WMI l'implémentation sur Windows. Get-CimInstance en PowerShell et Microsoft.Management.Infrastructure en C# se réclament de « CIM » parce que ce sont des API conformes à cette norme, mais elles se connectent à la même infrastructure WMI sous-jacente. Au quotidien, il suffit de retenir que l'on interroge les classes WMI (Win32_* et similaires) via des API de la famille CIM.
- Get-WmiObject n'est-il plus utilisable ?
- Il fonctionne encore sous Windows PowerShell 5.1, mais à partir de PowerShell 6 (donc dans PowerShell 7, la version actuelle), les cmdlets WMI v1 Get-WmiObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance et Remove-WmiObject ont été retirés et ne peuvent plus s'exécuter. 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'écrire avec les cmdlets CIM, même s'il doit tourner sous 5.1. Ainsi, il n'y a plus à réécrire la partie WMI lors d'une migration vers PowerShell 7.
- Pour accéder à WMI depuis C#, faut-il choisir System.Management ou Microsoft.Management.Infrastructure ?
- Les deux sont réservés à Windows et, depuis le .NET actuel, s'installent via un paquet NuGet. System.Management est l'API classique : il suffit de passer du WQL à un ManagementObjectSearcher, et cela suffit si l'essentiel est de récupérer des informations locales. Elle inclut aussi ManagementDateTimeConverter, qui convertit les dates DMTF. Microsoft.Management.Infrastructure (l'API MI), de son côté, partage le même système de types (CimSession / CimInstance) que les cmdlets CIM de PowerShell, et traite de façon cohérente les interrogations distantes via WSMan, les variantes asynchrones des méthodes et l'abonnement aux événements (Subscribe). Si vous intégrez vraiment des interrogations et de la surveillance de PC distants dans un produit, choisir l'API MI est le choix raisonnable.
- Get-CimInstance ne parvient pas à se connecter à un PC distant. Que faut-il vérifier ?
- Vérifiez d'abord si WinRM est configuré sur la machine cible. Une opération CIM qui spécifie -ComputerName crée une session temporaire via le protocole WSMan (WinRM), ce qui suppose que le service WinRM et un écouteur tournent sur la cible. winrm quickconfig applique la configuration par défaut : démarrer le service, créer un écouteur et ajouter une exception de pare-feu. Les ports par défaut sont 5985 pour HTTP et 5986 pour HTTPS : vérifiez aussi les pare-feu sur le chemin. Dans un groupe de travail, l'authentification mutuelle par Kerberos n'est pas disponible, ce qui peut exiger d'inscrire la cible dans la liste TrustedHosts du client. Pour une cible où WinRM ne peut absolument pas être configuré, vous pouvez à la place vous connecter en DCOM avec une option créée par New-CimSessionOption -Protocol Dcom.
- Pourquoi une date WMI revient-elle dans un format comme « 20260801100000.000000+540 » ?
- Les dates WMI sont stockées au format chaîne défini par la spécification CIM du DMTF (yyyymmddHHMMSS.mmmmmm±UUU, la valeur finale étant le décalage par rapport à l'UTC en minutes). Si vous lisez la valeur brute avec l'ancien Get-WmiObject ou avec System.Management, vous obtenez cette chaîne telle quelle. 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. Notez que, lorsque vous récupérez les données via une API de la famille CIM comme Get-CimInstance, les propriétés de date reviennent déjà converties en DateTime, de sorte que ce problème ne se pose 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.