枚举 WMI

枚举是在一组对象中移动,并可能在这样做时修改每个对象的行为。 例如,可以枚举一组 Win32_DiskDrive 对象以查找特定的序列号。 请注意,虽然可以枚举任何对象,但 WMI 只返回你具有安全访问权限的对象。

大型数据集的枚举可能需要大量资源并降低性能。 有关详细信息,请参阅改进枚举性能。 还可以使用更具体的查询来请求数据。 有关详细信息,请参阅查询 WMI

本主题讨论以下部分:

使用 PowerShell 枚举 WMI

如果不知道特定实例的对象路径,或者想要检索特定类的所有实例,请使用 Get-WmiObject,且类的名称在 -class 参数中。 如果想使用查询,可以使用 -query 参数。

以下过程描述了如何使用 PowerShell 枚举类的实例。

要使用 PowerShell 枚举类的实例

  1. 通过调用 Get-WmiObject cmdlet 枚举实例。

    Get-WmiObject 返回一个或多个 WMI 对象的集合,可以通过这些对象进行枚举。 有关详细信息,请参阅访问集合

    如果希望在另一个命名空间或另一台计算机上检索 WMI 类实例,请分别在 -computer 和 -namespace 参数中指定计算机和命名空间。 有关详细信息,请参阅创建 WMI 脚本。 这仅在具有适当的访问权限时才有效。 有关详细信息,请参阅维护 WMI 安全执行特权操作

  2. 使用集合的成员检索所需的任何单个实例。

以下代码示例检索 PowerShell 集合,然后显示本地计算机上逻辑驱动器的所有实例的大小属性。

$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." }
}

使用 C# 枚举 WMI (Microsoft.Management.Infrastructure)

  1. 添加对 Microsoft.Management.Infrastructure 引用程序集的引用。 (此程序集作为适用于 Windows 8 的 Windows 软件开发工具包 (SDK) 的一部分提供。)
  2. 为 Microsoft.Management.Infrastructure 命名空间添加 using 语句。
    using Microsoft.Management.Infrastructure;
  1. 实例化 CimSession 对象。 以下代码段使用 CimSession.Create 方法的标准“localhost”值。
    CimSession cimSession = CimSession.Create("localhost");
  1. 调用 CimSession.QueryInstances 方法,传递所需的 CIM 命名空间和要使用的 WQL。 以下代码段将返回两个实例,代表两个标准 Windows 进程,其中 handle 属性(代表进程 ID 或 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);
            }
        }
    }
}

使用 C# 枚举 WMI (System.Management)

如果不知道特定实例的对象路径,或者想要检索特定类的所有实例,请使用 ManagementClass 对象检索包含 WMI 命名空间中给定类的所有实例的 ManagementObjectCollection。 或者,可以通过 ManagementObjectSearcher 查询 WMI 以获得同一组对象。

注意

System.Management 是用于访问 WMI 的原始 .NET 命名空间;但是,此命名空间中的 API 通常较慢,并且相对于其更新式的 Microsoft.Management.Infrastructure 对应项,它们无法缩放。

 

以下过程说明了如何使用 C# 枚举类的实例。

要使用 C# 枚举类的实例

  1. 通过调用 ManagementClass.GetInstances 枚举实例。

    GetInstances 方法返回可枚举对象的集合或集。 有关详细信息,请参阅访问集合。 返回的集合实际上是一个 ManagementObjectCollection 对象,因此可以调用该对象的任何方法。

    如果希望在另一个命名空间或另一台计算机上检索 WMI 类实例,请在 path 参数中指定计算机和命名空间。 有关详细信息,请参阅创建 WMI 脚本。 这仅在具有适当的访问权限时才有效。 有关详细信息,请参阅维护 WMI 安全执行特权操作

  2. 使用集合的成员检索所需的任何单个实例。

以下代码示例检索 C# 集合,然后显示本地计算机上逻辑驱动器所有实例的大小属性。

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();

使用 VBScript 枚举 WMI

如果不知道特定实例的对象路径,或者想要检索特定类的所有实例,请使用 SWbemServices.InstancesOf 方法返回类的所有实例的 SWbemObjectSet 枚举。 或者,可以通过 SWbemServices.ExecQuery 查询 WMI 以获取同一组对象。

以下过程说明了如何使用 VBScript 枚举类的实例。

要使用 VBScript 枚举类的实例

  1. 通过调用 SWbemServices.InstancesOf 方法枚举实例。

    InstancesOf 方法返回可枚举对象的集合或集。 有关详细信息,请参阅访问集合。 返回的集合实际上是一个 SWbemObjectSet 对象,因此可以调用该对象的任何方法。

    如果希望在另一个命名空间或不同的计算机上检索 WMI 类实例,请在名字对象中指定计算机和命名空间。 有关详细信息,请参阅创建 WMI 脚本。 这仅在具有适当的访问权限时才有效。 有关详细信息,请参阅维护 WMI 安全执行特权操作

  2. 使用集合方法检索所需的任何单个实例。

以下代码示例检索 SWbemServices 对象,然后执行 InstancesOf 方法以显示本地计算机上所有逻辑驱动器实例的大小属性 。

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

使用 C++ 枚举 WMI

除了执行基本枚举外,还可以设置多个标志和属性来提高枚举的性能。 有关详细信息,请参阅改进枚举性能

要枚举 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::NextIEnumWbemClassObject::NextAsync 的多次调用遍历返回的枚举。

有关详细信息,请参阅处理类和实例信息