WMI-Enumeration

Enumeration ist der Vorgang, durch mehrere Objekte zu navigieren und dabei ggf. die jeweiligen Objekte zu ändern. Beispielsweise können Sie eine Reihe von Win32_DiskDrive-Objekten enumerieren, um eine bestimmte Seriennummer zu finden. Beachten Sie, dass Sie zwar alle Objekte enumerieren können, WMI jedoch nur Objekte zurückgibt, auf die Sie über Sicherheitszugriff verfügen.

Enumerationen großer Datasets können eine Vielzahl von Ressourcen erfordern und die Leistung beeinträchtigen. Weitere Informationen finden Sie unter Verbessern der Enumerationsleistung. Sie können Daten auch mit einer spezifischeren Abfrage anfordern. Weitere Informationen finden Sie unter Abfragen von WMI.

Dieses Thema umfasst die folgenden Abschnitte:

WMI-Enumeration mithilfe von PowerShell

Wenn Sie den Objektpfad für eine bestimmte Instanz nicht kennen oder alle Instanzen für eine bestimmte Klasse abrufen möchten, verwenden Sie Get-WmiObject mit dem Namen der Klasse im -class-Parameter. Wenn Sie eine Abfrage verwenden möchten, können Sie den -query-Parameter verwenden.

Nachstehend wird beschrieben, wie Sie die Instanzen einer Klasse mithilfe von PowerShell enumerieren.

So enumerieren Sie die Instanzen einer Klasse mithilfe von PowerShell

  1. Enumerieren Sie die Instanzen mit einem Aufruf des Get-WmiObject-Cmdlets.

    Get-WmiObject gibt eine Auflistung mit mindestens einem WMI-Objekt zurück, das Sie enumerieren können. Weitere Informationen finden Sie unter Zugreifen auf eine WMI-Auflistung.

    Wenn Sie eine WMI-Klasseninstanz in einem anderen Namespace oder auf einem anderen Computer abrufen möchten, geben Sie den Computer und den Namespace in den Parametern -computer bzw. -namespace an. Weitere Informationen finden Sie unter Erstellen eines WMI-Skripts. Dies funktioniert nur, wenn Sie über die entsprechenden Zugriffsberechtigungen verfügen. Weitere Informationen finden Sie unter Beibehalten der WMI-Sicherheit und Ausführen von privilegierten Vorgängen.

  2. Rufen Sie über die Elemente der Auflistung die gewünschten Instanzen einzeln ab.

Im folgenden Codebeispiel wird eine PowerShell-Auflistung abgerufen und dann die size-Eigenschaft für alle Instanzen von logischen Laufwerken auf dem lokalen Computer angezeigt.

$objCol = get-wmiobject -class "Win32_LogicalDisk"

# Or, alternately
#$objCol = get-wmiobject -Query "SELECT * FROM Win32_LogicalDisk"

foreach ($Drive in $objCol)
{
    if ($Drive.size -ne $null)
    { "Drive " + $Drive.deviceID + " contains " + $Drive.size + " bytes" }
    else
    { "Drive " + $Drive.deviceID + " is not available." }
}

WMI-Enumeration mithilfe von C# (Microsoft.Management.Infrastructure)

  1. Fügen Sie einen Verweis auf die Microsoft.Management.Infrastructure-Referenzassembly hinzu. (Diese Assembly ist im Windows Software Development Kit (SDK) für Windows 8 enthalten.)
  2. Fügen Sie eine using-Anweisung für den Microsoft.Management.Infrastructure-Namespace hinzu.
    using Microsoft.Management.Infrastructure;
  1. Instanziieren sie ein CimSession-Objekt. Der folgende Codeausschnitt verwendet den Standardwert „localhost“ für die CimSession.Create-Methode.
    CimSession cimSession = CimSession.Create("localhost");
  1. Rufen Sie die CimSession.QueryInstances-Methode auf, und übergeben Sie den gewünschten CIM-Namespace und die WQL, die verwendet werden soll. Der folgende Codeausschnitt gibt zwei Instanzen zurück, die zwei Windows-Standardprozesse darstellen, bei denen die handle-Eigenschaft (für eine Prozess-ID oder PID) den Wert 0 oder 4 aufweist.
    IEnumerable<CimInstance> queryInstances =     
      cimSession.QueryInstances(@"root\cimv2", 
                                "WQL", 
                                @"select name from win32_process where handle = 0 or handle = 4");
  1. Durchlaufen Sie die zurückgegebenen CimInstance-Objekte.
    foreach (CimInstance cimInstance in enumeratedInstances)
    { 
      Console.WriteLine("Process name: {0}", cimInstance.CimInstanceProperties["Name"].Value);  
    }

Das folgende Codebeispiel enumeriert alle Instanzen der Win32_Process-Klasse (die aktive Prozesse darstellt) auf dem lokalen Computer und gibt den Namen der einzelnen Prozesse aus.

Hinweis

In einer echten Anwendung würden Sie als Parameter den Computernamen („localhost“) und den CIM-Namespace („root\cimv2“) definieren. Aus Gründen der Einfachheit wurden diese in diesem Beispiel fest codiert.

 

using System;
using System.Collections.Generic;
using Microsoft.Management.Infrastructure;

public partial class MI
{
    static void PrintCimInstance(CimInstance cimInstance)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine("{0} properties", cimInstance.CimSystemProperties.ClassName);
        Console.ResetColor();

        Console.WriteLine(String.Format("{0,-5}{1,-30}{2,-15}{3,-10}", 
                                        "Key?", "Property", "Type", "Value"));

        foreach (var enumeratedProperty in cimInstance.CimInstanceProperties)
        {
            bool isKey = ((enumeratedProperty.Flags & CimFlags.Key) == CimFlags.Key);

            if (enumeratedProperty.Value != null)
            {
                Console.WriteLine(
                    "{0,-5}{1,-30}{2,-15}{3,-10}",
                    isKey == true ? "Y" : string.Empty,
                    enumeratedProperty.Name,
                    enumeratedProperty.CimType,
                    enumeratedProperty.Value);
            }
        }
        Console.WriteLine();
    }

    public static void QueryInstance(string query)
    {
        try
        {
            CimSession cimSession = CimSession.Create("localhost");

            IEnumerable<CimInstance> queryInstances = 
              cimSession.QueryInstances(@"root\cimv2", "WQL", query);
            foreach (CimInstance cimInstance in queryInstances)
            {
                //Use the current instance. This example prints the instance. 
                PrintCimInstance(cimInstance);
            }
        }
         catch (CimException ex) 
        { 
            // Handle the exception as appropriate.
            // This example prints the message.
            Console.WriteLine(ex.Message); 
        }
    }
}

using System;

namespace MIClientManaged
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Console.Write(&quot;Enter WQL (x = Quit): &quot;);
                string query = Console.ReadLine().ToUpper();
                if (query.CompareTo(&quot;X&quot;) == 0) break;
                MI.QueryInstance(query);
            }
        }
    }
}

WMI-Enumeration mithilfe von C# (System.Management)

Wenn Sie den Objektpfad für eine bestimmte Instanz nicht kennen oder alle Instanzen für eine bestimmte Klasse abrufen möchten, verwenden Sie das ManagementClass-Objekt, um eine ManagementObjectCollection-Auflistung abzurufen, die alle Instanzen einer bestimmten Klasse im WMI-Namespace enthält. Alternativ können Sie WMI über ManagementObjectSearcher abfragen, um den gleichen Satz von Objekten zu erhalten.

Hinweis

System.Management war der ursprüngliche .NET-Namespace, der für den Zugriff auf WMI verwendet wurde. Die APIs in diesem Namespace sind jedoch im Allgemeinen langsamer und skalieren im Vergleich zu ihren moderneren Microsoft.Management.Infrastructure-Entsprechungen nicht so gut.

 

Nachstehend wird beschrieben, wie Sie die Instanzen einer Klasse mithilfe von C# enumerieren.

So enumerieren Sie die Instanzen einer Klasse mithilfe von C#

  1. Enumerieren Sie die Instanzen mit einem Aufruf von ManagementClass.GetInstances.

    Die GetInstances-Methode gibt eine Auflistung oder einen Satz von Objekten zurück, die Sie enumerieren können. Weitere Informationen finden Sie unter Zugreifen auf eine WMI-Auflistung. Die zurückgegebene Auflistung ist ein ManagementObjectCollection-Objekt, sodass alle Methoden dieses Objekts aufgerufen werden können.

    Wenn Sie eine WMI-Klasseninstanz in einem anderen Namespace oder auf einem anderen Computer abrufen möchten, geben Sie den Computer und den Namespace im path-Parameter an. Weitere Informationen finden Sie unter Erstellen eines WMI-Skripts. Dies funktioniert nur, wenn Sie über die entsprechenden Zugriffsberechtigungen verfügen. Weitere Informationen finden Sie unter Beibehalten der WMI-Sicherheit und Ausführen von privilegierten Vorgängen.

  2. Rufen Sie über die Elemente der Auflistung die gewünschten Instanzen einzeln ab.

Im folgenden Codebeispiel wird eine C#-Auflistung abgerufen und dann die size-Eigenschaft für alle Instanzen von logischen Laufwerken auf dem lokalen Computer angezeigt.

using System.Management;
...

ManagementClass mc = new ManagementClass("Win32_LogicalDisk");
ManagementObjectCollection objCol = mc.GetInstances();

//or, alternately
//ManagementObjectSearcher mgmtObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDisk");
//ManagementObjectCollection objCol = mgmtObjSearcher.Get();

if (objCol.Count != 0)
{
   foreach (ManagementObject Drive in objCol)
   {
      if (Drive["size"] != null)
      {
         Console.WriteLine("Drive {0} contains {1} bytes.", Drive["deviceID"], Drive["size"]);
      }
      else
      {
         Console.WriteLine("Drive {0} is not available.", Drive["deviceID"]);
      }
   }
}
Console.ReadLine();

WMI-Enumeration mithilfe von VBScript

Wenn Sie den Objektpfad für eine bestimmte Instanz nicht kennen oder alle Instanzen für eine bestimmte Klasse abrufen möchten, verwenden Sie die SWbemServices.InstancesOf-Methode, um eine SWbemObjectSet-Enumeration aller Instanzen einer Klasse zurückzugeben. Alternativ können Sie WMI über SWbemServices.ExecQuery abfragen, um den gleichen Satz von Objekten zu erhalten.

Nachstehend wird beschrieben, wie Sie die Instanzen einer Klasse mithilfe von VBScript enumerieren.

So enumerieren Sie die Instanzen einer Klasse mithilfe von VBScript

  1. Enumerieren Sie die Instanzen mit einem Aufruf der SWbemServices.InstancesOf-Methode.

    Die InstancesOf-Methode gibt eine Auflistung oder einen Satz von Objekten zurück, die Sie enumerieren können. Weitere Informationen finden Sie unter Zugreifen auf eine WMI-Auflistung. Die zurückgegebene Auflistung ist ein SWbemObjectSet-Objekt, sodass alle Methoden dieses Objekts aufgerufen werden können.

    Wenn Sie eine WMI-Klasseninstanz in einem anderen Namespace oder auf einem anderen Computer abrufen möchten, geben Sie den Computer und den Namespace im Moniker an. Weitere Informationen finden Sie unter Erstellen eines WMI-Skripts. Dies funktioniert nur, wenn Sie über die entsprechenden Zugriffsberechtigungen verfügen. Weitere Informationen finden Sie unter Beibehalten der WMI-Sicherheit und Ausführen von privilegierten Vorgängen.

  2. Rufen Sie über die Methoden der Elemente die gewünschten Instanzen einzeln ab.

Im folgenden Codebeispiel wird ein SWbemServices-Objekt abgerufen und dann die InstancesOf-Methode ausgeführt, um die size-Eigenschaft für alle Instanzen von logischen Laufwerken auf dem lokalen Computer anzuzeigen.

Set objCol = GetObject("WinMgmts:").InstancesOf("Win32_LogicalDisk")
For Each Drive In objCol
    If Not IsNull(Drive.Size) Then    
       WScript.Echo ("Drive " & Drive.deviceid & " contains " & Drive.Size & " bytes")
    Else
       WScript.Echo ("Drive " & Drive.deviceid & " is not available.")
    End If
Next

WMI-Enumeration mithilfe von C++

Zusätzlich zur einfachen Enumeration können Sie mehrere Flags und Eigenschaften festlegen, um die Leistung Ihrer Enumeration zu erhöhen. Weitere Informationen finden Sie unter Verbessern der Enumerationsleistung.

So enumerieren Sie einen Objektsatz in WMI

  1. Erstellen Sie eine IEnumWbemClassObject-Schnittstelle, die den Satz von Objekten beschreibt, die Sie enumerieren möchten.

    Ein IEnumWbemClassObject-Objekt-Objekt enthält eine Liste, die einen Satz von WMI-Objekten beschreibt. Sie können die IEnumWbemClassObject-Methoden verwenden, um vorwärts zu enumerieren, Objekte zu überspringen, am Anfang zu beginnen und den Enumerator zu kopieren. In der folgenden Tabelle sind die Methoden aufgeführt, die zum Erstellen von Enumeratoren für verschiedene Typen von WMI-Objekten verwendet werden.

    Object Methode
    Klasse
    IWbemServices::CreateClassEnum
    [IWbemServices::CreateClassEnumAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createclassenumasync)
    Instanz
    IWbemServices::CreateInstanceEnum
    [IWbemServices::CreateInstanceEnumAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createinstanceenumasync)
    Abfrageergebnis
    IWbemServices::ExecQuery
    [IWbemServices::ExecQueryAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execqueryasync)
    Ereignisbenachrichtigung
    IWbemServices::ExecNotificationQuery
    [IWbemServices::ExecNotificationQueryAsync](/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execnotificationqueryasync)

     

  2. Durchlaufen Sie die zurückgegebene Enumeration mithilfe mehrerer Aufrufe von IEnumWbemClassObject::Next oder IEnumWbemClassObject::NextAsync.

Weitere Informationen finden Sie unter Bearbeiten von Klassen- und Instanzinformationen.