Перечисление WMI

Перечисление — это перемещение по набору объектов и, возможно, изменение каждого объекта по мере выполнения. Например, можно перечислить с помощью набора объектов Win32_DiskDrive для поиска определенного серийного номера. Обратите внимание, что хотя вы можете перечислить любой объект, WMI возвращает только объекты, к которым у вас есть доступ безопасности.

Перечисления больших наборов данных могут потребовать большого объема ресурсов и снизить производительность. Дополнительные сведения см. в разделе Повышение производительности перечисления. Вы также можете запросить данные с помощью более конкретного запроса. Дополнительные сведения см. в разделе Запрос WMI.

В этом разделе рассматриваются следующие разделы:

Перечисление WMI с помощью PowerShell

Если вы не знаете путь к объекту для определенного экземпляра или хотите получить все экземпляры для определенного класса, используйте командлет Get-WmiObject с именем класса в параметре -class . Если вы хотите использовать запрос, можно использовать параметр -query .

В следующей процедуре описывается перечисление экземпляров класса с помощью PowerShell.

Перечисление экземпляров класса с помощью PowerShell

  1. Перечислите экземпляры с помощью вызова командлета Get-WmiObject .

    Get-WmiObject возвращает коллекцию из одного или нескольких объектов WMI, с помощью которых можно выполнить перечисление. Дополнительные сведения см. в разделе Доступ к коллекции.

    Если вы хотите получить экземпляр класса WMI в другом пространстве имен или на другом компьютере, укажите компьютер и пространство имен в параметрах -computer и -namespace соответственно. Дополнительные сведения см. в разделе Создание скрипта WMI. Это работает, только если у вас есть соответствующие права доступа. Дополнительные сведения см. в разделах Поддержка безопасности WMI и Выполнение привилегированных операций.

  2. Получите все нужные экземпляры с помощью элементов коллекции.

В следующем примере кода извлекается коллекция PowerShell, а затем отображается свойство size для всех экземпляров логических дисков на локальном компьютере.

$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 с помощью C# (Microsoft.Management.Infrastructure)

  1. Добавьте ссылку на эталонную сборку Microsoft.Management.Infrastructure . (Эта сборка поставляется в составе пакета sdk для Windows для Windows 8.)
  2. Добавьте оператор using для пространства имен Microsoft.Management.Infrastructure .
    using Microsoft.Management.Infrastructure;
  1. Создание экземпляра объекта CimSession . В следующем фрагменте кода используется стандартное значение localhost для метода CimSession.Create .
    CimSession cimSession = CimSession.Create("localhost");
  1. Вызовите метод CimSession.QueryInstances , передав требуемое пространство имен CIM и WQL для использования. Следующий фрагмент кода вернет два экземпляра, представляющих два стандартных процесса Windows, в которых свойство handle (представляющее идентификатор процесса или PID) имеет значение 0 или 4.
    IEnumerable<CimInstance> queryInstances =     
      cimSession.QueryInstances(@"root\cimv2", 
                                "WQL", 
                                @"select name from win32_process where handle = 0 or handle = 4");
  1. Циклическое перебирание возвращенных объектов CimInstance .
    foreach (CimInstance cimInstance in enumeratedInstances)
    { 
      Console.WriteLine("Process name: {0}", cimInstance.CimInstanceProperties["Name"].Value);  
    }

В следующем примере кода перечисляются все экземпляры класса Win32_Process (который представляет активные процессы) на локальном компьютере и выводится имя каждого процесса.

Примечание

В реальном приложении в качестве параметров можно определить имя компьютера (localhost) и пространство имен CIM ("root\cimv2"). В целях простоты они были жестко закодированы в этом примере.

 

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 с помощью C# (System.Management)

Если вы не знаете путь к объекту для определенного экземпляра или хотите получить все экземпляры для определенного класса, используйте объект ManagementClass , чтобы получить объект ManagementObjectCollection , содержащий все экземпляры данного класса в пространстве имен WMI. Кроме того, можно запросить WMI через ManagementObjectSearcher , чтобы получить тот же набор объектов.

Примечание

System.Management — это исходное пространство имен .NET, используемое для доступа к WMI; Однако API-интерфейсы в этом пространстве имен обычно работают медленнее и не масштабируются по сравнению с более современными аналогами Microsoft.Management.Infrastructure .

 

В следующей процедуре описывается перечисление экземпляров класса с помощью C#.

Перечисление экземпляров класса с помощью C #

  1. Перечислите экземпляры с помощью вызова ManagementClass.GetInstances.

    Метод GetInstances возвращает коллекцию или набор объектов, с помощью которых можно выполнить перечисление. Дополнительные сведения см. в разделе Доступ к коллекции. Возвращаемая коллекция на самом деле является объектом ManagementObjectCollection , поэтому можно вызвать любой из методов этого объекта.

    Если вы хотите получить экземпляр класса WMI в другом пространстве имен или на другом компьютере, укажите компьютер и пространство имен в параметре path . Дополнительные сведения см. в разделе Создание скрипта WMI. Это работает, только если у вас есть соответствующие права доступа. Дополнительные сведения см. в разделах Поддержка безопасности WMI и Выполнение привилегированных операций.

  2. Получите все нужные экземпляры с помощью элементов коллекции.

В следующем примере кода извлекается коллекция C#, а затем отображается свойство size для всех экземпляров логических дисков на локальном компьютере.

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 с помощью VBScript

Если вы не знаете путь к объекту для конкретного экземпляра или хотите получить все экземпляры для определенного класса, используйте метод SWbemServices.InstancesOf , чтобы вернуть перечисление SWbemObjectSet всех экземпляров класса. Кроме того, можно запросить WMI через SWbemServices.ExecQuery , чтобы получить тот же набор объектов.

В следующей процедуре описывается перечисление экземпляров класса с помощью VBScript.

Перечисление экземпляров класса с помощью VBScript

  1. Перечислите экземпляры с помощью вызова метода SWbemServices.InstancesOf .

    Метод InstancesOf возвращает коллекцию или набор объектов, с помощью которых можно выполнить перечисление. Дополнительные сведения см. в разделе Доступ к коллекции. Возвращаемая коллекция фактически является объектом SWbemObjectSet , поэтому можно вызвать любой из методов этого объекта.

    Если вы хотите получить экземпляр класса WMI в другом пространстве имен или на другом компьютере, укажите компьютер и пространство имен в моникере. Дополнительные сведения см. в разделе Создание скрипта WMI. Это работает, только если у вас есть соответствующие права доступа. Дополнительные сведения см. в разделах Поддержка безопасности WMI и Выполнение привилегированных операций.

  2. Получите все нужные экземпляры с помощью методов коллекций.

В следующем примере кода извлекается объект SWbemServices , а затем выполняется метод InstancesOf для отображения свойства size для всех экземпляров логических дисков на локальном компьютере.

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 с помощью C++

Помимо выполнения базового перечисления, можно задать несколько флагов и свойств, чтобы повысить производительность перечисления. Дополнительные сведения см. в разделе Повышение производительности перечисления.

Перечисление набора объектов в WMI

  1. Создайте интерфейс IEnumWbemClassObject , описывающий набор объектов, которые требуется перечислить.

    Объект IEnumWbemClassObject содержит список, описывающий набор объектов WMI. Методы IEnumWbemClassObject можно использовать для перечисления переадресации, пропуска объектов, начала в начале и копирования перечислителя. В следующей таблице перечислены методы, используемые для создания перечислителей для различных типов объектов WMI.

    Объект Метод
    Класс
    IWbemServices::CreateClassEnum
    [IWbemServices::CreateClassEnumAsync] (/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createclassenumasync)
    Экземпляр
    IWbemServices::CreateInstanceEnum
    [IWbemServices::CreateInstanceEnumAsync] (/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-createinstanceenumasync)
    Результат запроса
    IWbemServices::ExecQuery
    [IWbemServices::ExecQueryAsync] (/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execqueryasync)
    Уведомление о событии
    IWbemServices::ExecNotificationQuery
    [IWbemServices::ExecNotificationQueryAsync] (/windows/desktop/api/WbemCli/nf-wbemcli-iwbemservices-execnotificationqueryasync)

     

  2. Обход возвращаемого перечисления с помощью нескольких вызовов IEnumWbemClassObject::Next или IEnumWbemClassObject::NextAsync.

Дополнительные сведения см. в разделе Управление сведениями о классах и экземплярах.