1 概念
WMI 是微软的基于面向对象体系构造的操作系统管理的有效工具,它支持对于计算机的本地与与远程管理。WMI有个特点就是我们第三方可以扩展面向对象的体系提供者,包括新建新的提供者以及继承现有提供者,我们可以借此编写第三方的提供者,提供者对象是自描述的。
程序使用vs2013,.net 4.5。
程序引用的程序集如下图:


Key.snk 测试,实验用的签名文件
ProviderSample.cs 包括单实例、多实例两个提供者源码,这里我们先把公共部分写出来,单实例、多实例的代码在后面附上。
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Management;
using System.Management.Instrumentation;
using System.Security.Principal;
using System.Text;
// 本程序集的默认名称空间以及宿主配置
[assembly: WmiConfiguration(@"root\cimv2", HostingModel = ManagementHostingModel.LocalService)]
namespace WMIProvider
{
#region 安装器
/// <summary>
/// 提供者默认的管理安装器
/// </summary>
[System.ComponentModel.RunInstaller(true)]
public class MyInstall : DefaultManagementInstaller
{
}
#endregion 安装器
要指出的是,程序集要以签名的方式进行编译,m名称叫WMIProvider.dll,然后把程序集使用以下步骤进行部署:
以管理员权限运行
VS2013 开发人员命令提示,命令行,然后:
| 安装 | 1、gacutil -i WMIProvider.dll |
| 2、installutil WMIProvider.dll | |
| 卸载 | 1、installutil WMIProvider.dll /u |
| 2、gacutil -u WMIProvider.dll |
如果安装过程有问题,可以试试:
gacutil -i WMIProvider.dll –f
2.单实例提供者
2.1 源码
#region 单实例
/// <summary>
/// WMI提供者,单实例的例子,不能有键
/// </summary>
/// <remarks>
/// 此标签默认多实例,单实例要加上(Singleton = true)
/// </remarks>
[ManagementEntity(Singleton = true)]
public class SampleSingle
{
/// <summary>
/// 只读的例子
/// </summary>
[ManagementProbe]
public virtual string ReadonlySampleName { get; private set; }
/// <summary>
/// 可写的例子,配置为马上更新
/// </summary>
/// <remarks>
/// 配置为自动更新,马上更新。配置为 Apply 支持批量提交,需单独的提交方法
/// </remarks>
[ManagementConfiguration(Mode=ManagementConfigurationType.OnCommit)]
public virtual int WriteableValue { get; set; }
/// <summary>
/// 单实例变量,使用单根模式
/// </summary>
private static SampleSingle sampleSingle;
/// <summary>
/// 绑定方法,单实例绑定时方法不能有参数
/// </summary>
[ManagementBind]
public static SampleSingle Build()
{
if (sampleSingle == null)
{
sampleSingle = new SampleSingle();
sampleSingle.ReadonlySampleName = "ReadonlySampleName";
sampleSingle.WriteableValue = 100;
}
return sampleSingle;
}
}
#endregion 单实例
2.2 使用
1、vs:
打开vs的服务器资源管理器,找到管理类节点:

在弹出菜单中选择
添加类,会弹出添加类对话框:

点击root\cimv2前的+ 号,会出现对象列表,在其中选择SampleSingle,点击添加按钮,再点击确定,它就会出现在管理类下面:

点击他前面的 +号 就会出现一个 @的子节点, 按照WMI规定,单实例名称都会显示为 @ ,下面为截图:

选中此节点,接着按下 F4键让 vs 的属性框出现:

尝试修改 ReadonlySampleName和 WriteableValue,就会发现 ReadonlySampleName无法修改,而 WriteableValue可以:

2、wbemtest:
在电脑的运行菜单中,键入以下命令:
Wbemtest
点击运行,会出现下面的窗口:

点击连接,显示以下窗口:

点击连接后,我们的窗口多了些有效的按钮:

点击查询:

输入 sql 语句:
SELECT * FROM SampleSingle

点击应用,会出现结果窗口:

点击关闭结束。
3 多实例提供者
1 源码
#region 多实例
/// <summary>
/// 存储内部数据的实例
/// </summary>
public class SampleMultiInstance
{
/// <summary>
/// 只读的例子
/// </summary>
public virtual int ReadonlyValue { get; set; }
/// <summary>
/// 可写的例子
/// </summary>
public virtual int WriteableValue { get; set; }
}
/// <summary>
/// WMI 提供者,多实例提供者的例子,有键,有绑定,绑定参数为键
/// </summary>
[ManagementEntity]
public class SampleMulti
{
/// <summary>
/// 静态构造
/// </summary>
static SampleMulti()
{
var qs = new SampleMultiInstance() {ReadonlyValue = 10, WriteableValue = 100};
store.Add("key1", qs);
qs = new SampleMultiInstance() {ReadonlyValue = 11, WriteableValue = 101};
store.Add("key2", qs);
qs = new SampleMultiInstance() { ReadonlyValue = 12, WriteableValue = 102 };
store.Add("key3", qs);
qs = new SampleMultiInstance() { ReadonlyValue = 13, WriteableValue = 103 };
store.Add("key4", qs);
}
/// <summary>
/// 存储键与内部数据实例
/// </summary>
private static Dictionary<string, SampleMultiInstance> store = new Dictionary<string, SampleMultiInstance>();
/// <summary>
/// 提供者键值,只读
/// </summary>
[ManagementKey]
public string Id { get; private set; }
/// <summary>
/// 绑定方法,也可以是构造,里面的参数要和键值名称相同,在参数上使用 [ManagementName("Id")] 标签
/// </summary>
[ManagementBind]
public SampleMulti(
[ManagementName("Id")]
string id)
{
Id = id;
}
/// <summary>
/// 实例集合枚举器
/// </summary>
/// <returns>集合</returns>
[ManagementEnumerator]
public static System.Collections.IEnumerable GetInstances()
{
foreach (var qs in store.Keys)
yield return new SampleMulti(qs);
}
/// <summary>
/// 只读的例子
/// </summary>
[ManagementProbe]
public virtual int ReadonlyValue
{
get
{
return store[Id].ReadonlyValue;
}
private set
{
store[Id].ReadonlyValue = value;
}
}
/// <summary>
/// 可写的例子,配置为马上更新
/// </summary>
[ManagementConfiguration(Mode = ManagementConfigurationType.OnCommit)]
public virtual int WriteableValue
{
get
{
return store[Id].WriteableValue;
}
set
{
store[Id].WriteableValue = value;
}
}
/// <summary>
/// 方法调用,仅支持多实例提供者
/// </summary>
/// <param name="value">方法值</param>
/// <returns>布尔型</returns>
[ManagementTask]
public bool IncValue(int value)
{
ReadonlyValue += value;
WriteableValue -= value;
return false;
}
}
#endregion 多实例
2 使用
1、vs:
与单实例类似添加,但是管理对象为列表:

选中key1节点,接着按下 F4键让 vs 的属性框出现:

将 WriteableValue 的值由100 改为2000

点击管理类上的 key1 节点的上下文菜单,选中 IncValue在value 中输入 1000,点击调用,会返回 false ,点击确定。

在key1 节点,选中刷新,就会看到:

2、wbemtest:
与单实例类似,只是 sql 语句不同。
select * from SampleMulti
