wxzself经验分享 WMI 提供者实现

0
(0)

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

这篇文章有用吗?

点击星号为它评分!

平均评分 0 / 5. 投票数: 0

到目前为止还没有投票!成为第一位评论此文章。

很抱歉,这篇文章对您没有用!

让我们改善这篇文章!

告诉我们我们如何改善这篇文章?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注