WMI 接口 for .NET
一个类库,用于辅助编写 WMI 应用程序。

引言
在过去的几年里,我断断续续地编写了一些小型 WMI 应用程序,并且一直觉得用 .NET 编写这类应用程序总显得有些麻烦。我忍不住想,.NET 中一定有更好的方法来编写 WMI 应用程序。于是我开始在互联网上搜索任何可能有助于加快开发进程的内容。我到处都能找到文章,展示人们如何使用 .NET 中的 System.Management
命名空间来实现他们的目标。其中一些文章写得非常好,有些可能还有改进的空间。但它们都有一个共同点,那就是文章下方总有一些评论问:“如何实现‘这个’……”或“是否可能实现‘这个’……”。这让我思考,这篇文章是否真的解答了人们的疑问?我找到的答案是,是的,也否。
用 .NET 编写 WMI 应用程序的一个问题是,没有直接的方法来处理内置类的属性和方法。所有解决方案最终都让开发人员通过 ManagementObject
对象中的字符串索引来引用属性。
ManagementObject oMngObject = MyObejctCollection[0];
lblDemo.Text = oMngObject[“Manufacturer”];
虽然这是处理 WMI 属性的一种有效方法,但如果你不知道要访问的属性的名称,那么它就没什么用了。这就是 EasyWMI
的用武之地。
EasyWMI 详解
我开发了 EasyWMI
类库,以帮助加快开发 WMI 驱动应用程序的开发进程。它包含了root/cimv2命名空间中绝大多数的 Win32 类。该库主要包含两部分:控制器(controllers)和模型(models)。模型是直接从 Windows WMI 中提取的 Win32
类,包含每个类的所有属性和方法。控制器负责创建和填充每个模型。对于每个模型,都有一个相应的控制器与之对应。控制器的命名方案与模型的命名方案相同,只是去掉了前缀 Win32_
。例如,Win32_Process
类有一个对应的控制器,名为 Process
。在使用 EasyWMI
的源代码时,需要注意一点,我并没有手动编写所有的模型和控制器。实际上,我为此目的构建了一个使用 CodeDOM 的代码生成器。所以在处理实际源代码时,请注意,缩进可能有些混乱,阅读起来会有些不方便,但并不困难。
Using the Code
使用 EasyWMI
非常简单。创建一个你想要使用的类控制器的实例,然后运行 SelectAll()
方法。每个控制器包含 5 个重载构造函数;默认构造函数假定为“localhost”。
// Create a new instance of ComputerSystem.
ComputerSystem CS = new ComputerSystem();
IList CSCollection = CS.SelectAll();
Win32_ComputerSystem MyCS = CSCollection[0];
SelectAll()
返回一个通用 IList<t />
集合,类型为 Win32_CLASSNAME
。某些类只返回集合中的一个项,例如 ComputerSystem
和 OperatingSystem
。现在你可以访问该特定 Win32_ComputerSystem
类型对象的全部方法和属性了。对于返回多个对象的类,你可以简单地使用 foreach
循环来遍历集合。
static void DisplayLogicalDisks(IList Drives)
{
SetupSection("Logical Disks");
try
{
foreach (Win32_LogicalDisk LogicalDisk in Drives)
{
Console.WriteLine("Drive " + LogicalDisk.DeviceID);
Console.WriteLine(" Volume:\t\t" + LogicalDisk.VolumeName);
Console.WriteLine(" Size:\t\t" + ConvertToMB(LogicalDisk.Size));
Console.WriteLine(" Free Space:\t\t" + ConvertToMB
(LogicalDisk.FreeSpace));
Console.WriteLine(" File System:\t" + LogicalDisk.FileSystem);
Console.WriteLine(" Caption:\t\t" + LogicalDisk.Caption);
Console.WriteLine(" Serial:\t\t" + LogicalDisk.VolumeSerialNumber);
Console.WriteLine();
}
}
catch (Exception ex)
{
Console.WriteLine("Error retrieving information.");
Console.WriteLine("Message: " + ex.Message);
}
Console.WriteLine();
}
现在你大致了解了访问每个 Win32 类的属性有多么简单,那么如何使用它们的方法呢?很简单,就像使用任何方法一样使用它们。
string Domain;
string User;
Process SysProcess = new Process();
IList Processes = SysProcess.SelectAll();
foreach (Win32_Process Process in Processes)
{
if (Process.Name == "iexplore.exe")
{
Process.GetOwner(out Domain, out Username);
Process.Terminate(0);
}
}
你也可以指定一个自定义查询来代替默认的 select * from
。
CS = new ComputerSystem(ComputerName);
CS.EasyWMICfgUsername = @"yourdomain\username";
CS.EasyWMICfgPassword = "password";
CS.EasyWMICfgQuery = "select Manufacturer from";
CS.SetScope();
CSCollection = CS.SelectAll();
你可能会注意到,在设置了一些配置选项后,我调用了 SetScope()
方法。在运行 SelectAll()
方法之前,任何时候更改了配置选项,你都需要运行 SetScope()
方法。
结论
尽管这可能不是使用 .NET 与 WMI 接口的最完整、最好的方法,但我希望它能帮助简化 WMI 的使用并加快你的开发进程。
历史
目前还没有更新。