WMI 初探——MOF 建立命名空间与类和 C# 增删查改

§1 背景介绍

WMI Provider:对 WMI 对象的定义和操作,包含 MOF 和 DLL 文件。其中,MOF (Managed Object Format,托管对象格式) 中定义了 WMI 的命名空间或类,及类中的属性和方法; DLL 文件进行类实例的增删查改、类方法的实现。
详见:Designing Managed Object Format (MOF) Classes - Windows applications | Microsoft Docs

§2 使用 C++ 建立 MOF 文件

2.1 建立命名空间

2.1.1 介绍

  1. WMI 中所有命名空间实质上是系统类 __Namespace 中的一个实例, __Namespace 仅有一个属性 Name 。在建立命名空间时需要指定一个以字母开头,由字母、数字、下划线组成的名称,区分大小写,且不能与已有命名空间名称重复。
    我们可以建立如下格式的命名空间:Root/myCompany/myProduct
  2. 在建立命名空间时,我们可以选择在已有的命名空间下建立 (Child Namespace) ,或是在根目录下建立 (Sibling Namespace) 。
    官方不建议建立 Child Namespace ,因为在其 Parent Namespace 的模式更新时,所有类实例将被重建,这可能会导致我们建立的命名空间被删除。因此,在我们不能直接控制 Parent Namespace 时,建立 Sibling Namespace 更为保险

2.1.2 操作步骤

使用 MOF 文件建立命名空间需要三步:

  1. 在最前面插入 #pragma namespace 表示之后的代码在哪个命名空间生效;
  2. 在 __Namespace 类中建立一个实例;
  3. 保存为 .mof 文件,使用 mofcomp 工具 (在 %Windir%\System32\wbem 目录中) 编译。

之后查看 WMI 就可以看到建立的命名空间了。

2.1.3 代码示例

#pragma autorecover
#pragma namespace("\\\\.\\Root")

instance of __Namespace 
{
    Name = "MyNamespace";
};

为了保证我们定义的命名空间、类能够在 WMI 遇到错误重启时能够恢复,我们需要在 MOF 文件第一行加入 #pragma autorecover

2.1.4 本节详见

主要内容:

  • Creating Hierarchies Within WMI - Windows applications | Microsoft Docs
  • mofcomp - Windows applications | Microsoft Docs
  • Using WMI Management Tools | Microsoft Docs

更多关于子命名空间、使用 WMI API 实现:

  • Creating a Child Namespace with MOF Code - Windows applications | Microsoft Docs
  • Creating a Namespace with the WMI API - Windows applications | Microsoft Docs

2.2 建立类

2.2.1 介绍

  1. 在 WMI 中存在基类和派生类。当很多派生类有着同样的属性时,可以将这些属性和方法放进基类中。
  2. 类的名称需要以字母开头,前后端不能使用下划线,由字母、数字、下划线组成,区分大小写,命名规则一致。好的命名应该是 “厂商名称_描述” 的构造形式。
    例如:Kabuto_Security
  3. 类本身在 Provider 运行时不会被更改,只能在 WMI 服务停止时被修改。

2.2.2 操作步骤

以下仅说明使用 MOF 文件建立基类的方法,需要三步:

  1. 在最前面插入 #pragma namespace 表示之后的代码在哪个命名空间生效;
  2. 插入以 class 为开头的代码段,内附字段和方法;
  3. 保存为 .mof 文件,使用 mofcomp 工具编译。

之后查看 WMI 就可以看到建立的基类了。

2.2.3 代码示例

#pragma autorecover
#pragma namespace("\\\\.\\Root\\Kabuto")

class Kabuto_Configuration
{
    [key] string code;
    string rootPath;
};

其中,[key] 主键表示实例的唯一性,一个类也可以有多个主键,详见 Adding a Qualifier - Windows applications | Microsoft Docs 。

2.2.4 本节详见

主要内容:

  • Creating a WMI Base Class - Windows applications | Microsoft Docs

更多关于派生类、修饰符、添加方法、别名、使用 C++ 实现:

  • Creating a WMI Derived Class - Windows applications | Microsoft Docs
  • Creating a WMI Method - Windows applications | Microsoft Docs
  • Creating a WMI Alias - Windows applications | Microsoft Docs
  • Adding a Qualifier - Windows applications | Microsoft Docs

§3 C# 对 WMI 类实例的增删查改

以下所有操作都需要先建立 WMI 命名空间的连接,进入需要操作的类。

// 进入 WMI 中刚才建立的 "root\\Kabuto" 命名空间
ManagementScope managementScope = new managementScope("root\\Kabuto");
managementScope.Connect();
// 进入需要操作的类,需要指定命名空间
ManagementClass newClass = new ManagementClass("Kabuto_Security")
{
    Scope = managementScope
};

3.1 增改类实例

本节及之后两节主要使用 .NET 中的 System.Management 命名空间来实现与 WMI 的交互,因此程序开头需要 using System.Management;

// 新建实例
ManagementObject newInstance = newClass.CreateInstance();
newInstance["code"] = "001";
newInstance["rootPath"] = "C:/";
// 提交更改
newInstance.Put();

当主键值不存在时,新增实例;当主键值存在时,更新实例。

3.2 删除类实例

// 获取所有实例
ManagementObjectCollection collection = newClass.GetInstances();
foreach (ManagementObject obj in collection)
{
    if (obj["code"].ToString() == "001")
    {
        // 删除实例
        obj.Delete();
        break;
    }
}

3.3 查询类实例

// 获取所有实例
ManagementObjectCollection collection = newClass.GetInstances();
Console.WriteLine(collection.Count);
foreach (ManagementObject obj in collection)
{
    // 打印实例信息
    Console.WriteLine(obj["code"]);
    Console.WriteLine(obj["rootPath"]);
}

§4 总结

本文为初探 WMI ,仅能满足简单需求,后续需要的学习还有很多。
更多资料详见:

  • Using WMI - Windows applications | Microsoft Docs

你可能感兴趣的:(WMI 初探——MOF 建立命名空间与类和 C# 增删查改)