Utiliser WMI/CIM depuis C# et PowerShell — guide pratique d'inventaire matériel, de surveillance des processus et d'interrogations distantes

· Mis à jour le: · · 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

Exigences courantes et WMI/CIMAfficher 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 gestionNuméro de série et nom de modèleWMI (infrastructure qui utilise la norme CIM)Surveillance de l'espace disque libreDétection du démarrage des processusInterrogation de PC distants

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.

Le principe de décisionLe 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 directementOuiNonY a-t-il un mécanisme dédié ?Utiliser le mécanisme dédiéUtiliser WMI / CIMInterrogations transversales et distantesCmdlets dédiés basés sur CIMN'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
Relation entre la norme CIM et l'implémentation WMILa 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 WMIDéfini et maintenu par le DMTFCIM (modèle standard de l'industrie)WBEM (initiative de l'industrie)WMI (implémentation Microsoft)MI (nouvelle génération, entièrement compatible)API de la famille CIM (PowerShell / C#)

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) ou Win32_Process (un processus). Les classes propres à Windows qui dérivent des classes de la norme CIM (CIM_LogicalDisk et similaires) portent le préfixe Win32_.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.

La structure d'une interrogation WMIUne 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éInterroger avec WQLEspace de noms root/CIMV2Classe Win32_*FournisseurInterroge l'OS sur placeRenvoie 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 ».

Pourquoi les scripts nouveaux doivent s'écrire avec CIMUn 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 migrationCmdlets WMICmdlets CIMUn script nouveauAvec quoi l'écrire ?S'exécute sous 5.1Fonctionne aussi sous 5.1Retiré dans PowerShell 7Réécrire à la migrationAucun 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.

Appel d'une méthode sur une CimInstanceLa 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-CimMethodGet-CimInstanceObjet CimInstanceDates déjà converties en DateTimeLes méthodes WMI passent par un autre point d'entréeLa passer à Invoke-CimMethodAppel 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.

La base d'une surveillance de disque sans agentFiltrer 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 agentScript de récupération de l'espace libreFiltrer sur DriveType = 3Exclut les lecteurs amovibles et similairesVia une session CIML'exécuter contre chaque serveurSurveillance 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

Choisir un mode de connexion CIMSans 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éNonOuiPonctuelPlusieursExécuter sans passer CimSessionComputerName est-il spécifié ?Connexion COM au WMI localPlusieurs opérations sur la même cible ?Session WSMan temporaireRéutiliser New-CimSessionCréée à chaque interrogationCible sans WinRM configuré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 quickconfig fait 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 avec winrm 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 TrustedHosts du 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
Vérifier les prérequis des interrogations distantesSur 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éewinrm quickconfigService mis en démarrage automatiqueÉcouteur HTTP créé (5985)Exception de pare-feuÉcouteur HTTPS (5986)Préparer un certificat et configurer séparémentEnvironnement de groupe de travailN'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.

Récupération des propriétés et piège de la conversionLes 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 InvalidCastExceptionRécupéré via l'indexeurRevient comme objectVérifier le type CIM dans la documentationConvertir vers le type correctConvertir en supposant que c'est un intInvalidCastException

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 ».

Prototyper en PowerShell et transcrire dans C#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 naturellementPrototyper en PowerShellCmdlets CIMImplémentation réelle en C#API MILe même type CimInstanceLa 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) : ManagementDateTimeConverter fournit la conversion dans les deux sens entre le format DMTF et DateTime / 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).LastBootUpTime peut s’utiliser directement comme DateTime dans un calcul.
Traitement du format de date DMTFLes 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êmeSystem.ManagementAPI de la famille CIMChaîne au format DMTFQuelle API l'a récupérée ?ManagementDateTimeConverterRenvoyée déjà convertie en DateTimeConvertir en DateTime / TimeSpanDécouper la chaîne soi-mêmeNe 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.

Une disposition de surveillance pour les environnements utilisateur standardUn 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 interprocessusCommunication interprocessusService Windows de surveillanceS'abonne à la trace de démarrageS'exécute comme LocalSystem ou similaireL'application elle-même (utilisateur standard)

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
Le flux d'un abonnement à l'événement de démarrage de processusUne 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 termineWMISession PowerShellWMISession PowerShellExécuter avec des privilèges d'administrateurEnregistrer l'abonnement avec Register-CimIndicationEventUn événement arrive à chaque démarrage de processusExécuter -ActionLe 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.

Deux méthodes d'abonnement pour détecter le démarrage des processusWin32_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 appartientDétecter le démarrage des processusWin32_ProcessStartTrace__InstanceCreationEventS'abonner à une trace du noyauInterroge à l'intervalle WITHINCompromis 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 ».

Le cycle de vie de l'abonnement dans une surveillance permanenteDans 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éRedémarrage du service ou erreurAbonnéAbonnement tombéRéinscrire

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 de Win32_Process avec 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 -Filter et les colonnes avec -Property, et utilisez -KeyOnly si 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_Process une 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

Anti-modèles de performance et par quoi les remplacerAller 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 CIMAller vers SELECT * par habitudeRestreindre avec Filter et PropertyKeyOnly si vous ne voulez que les clésPolling à intervalle courtRemplacer par un abonnement aux événementsComputerName machine par machineRé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 ».

Choix du fournisseur dans un environnement 64 bitsPar 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 vue32 bits64 bitsQuel est le nombre de bits de l'appelant ?Le fournisseur 32 bits répondLe fournisseur 64 bits répondLes valeurs du Registre viennent de Wow6432NodeSpécifier __ProviderArchitectureDemander 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.

Isoler une incohérence du référentiel WMILorsque 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 gesteOuiNonErreurs telles que classe introuvablewinmgmt /verifyrepositoryLe résultat est-il inconsistent ?winmgmt /salvagerepositorySoupçonner une cause ailleurs dans l'OSLe contenu lisible est fusionnéSupprimer ou réinitialiser le référentielPas 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

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.

Références

  1. 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

  2. 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

  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

  4. 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

  5. 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

  6. 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

  7. 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

  8. 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

  9. 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

  10. 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

  11. 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

  12. 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

  13. 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 récents partageant les mêmes étiquettes, pour approfondir des sujets proches.

Ces pages replacent le sujet dans un contexte plus large de services et de décisions.

Cet article est directement lié aux services suivants.

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.

Retour au blog