在《WMI技术介绍和应用——Instance/Method Provider》一文中,我们介绍了Instance和Method Provider的编写方法。本文我们将介绍更有意思的“事件提供者”。在《WMI技术介绍和应用——事件通知》中,我们曾经提到事件是分为两种:intrinsic event和extrinsic event。这两种事件提供者在编写上也非常类似,我们先以extrinsic event为例。(转载请指明出于breaksoftware的csdn博客)

intrinsic event provider

之前生成工程的过程和《WMI技术介绍和应用——Instance/Method Provider》中介绍的一致,但是我们这次要新增的ATL class则不同

在”名称“页,我们在short name中填上我们事件提供者的名称”TestEvent",其他输入框内容将自动生成。

事件类型我们选择extrinsic event,其他不填

在“属性”页,将Threading model设置为Both。Support选项都勾选上

执行完之后,我们就生成了一个mof文件、一个TestEvent.h和TestEvent.cpp文件。我们继续从mof文件入手,我们申明一个事件类

[Locale(1033) : ToInstance,UUID("{E5EDE7F6-D9F9-4195-8E97-643B71F2FB91}") : ToInstance]
class ClassEventInstance: __ExtrinsicEvent
{
string name = "CIN";
string value = "CIV";
};

然后注册一个事件提供者,并指定查询命令

instance of __EventProviderRegistration
{provider = $TestEvent;EventQueryList = {"select * from ClassEventInstance"};
};

再回到cpp代码文件,首先我们要修改类名

const static WCHAR * s_pMyClassName = L"ClassEventInstance"; 

其次我们要修改AccessCheck函数,删除掉这行,否则我们查询不会成功

hr = WBEM_E_ACCESS_DENIED;

我们需要修改ProvideEvents函数,在该函数末尾新增如下逻辑

    HANDLE hThread = (HANDLE)_beginthread(ThreadRoutine, 0, this);CloseHandle(hThread);

我们启动一个线程,用于事件的发送。我们传入this指针只是为了之后调用我们类中的一个方法。我们看下线程函数

static void ThreadRoutine(void* param) {OutputTrace("CTestEvent::ThreadRoutine");CoInitializeEx(NULL, COINIT_MULTITHREADED);CTestEvent* pThis = (CTestEvent*)(param);while(true) {Sleep(1000*2);pThis->FireEvent();}CoUninitialize();
};

这段逻辑,我们在一个死循环中每隔两秒钟触发一次事件——FireEvent。FireEvent本来是模板自动生成的,而我们借用它实现事件的触发。这儿需要注意一个文件,本文主要讲解搭建的关键步骤,而对很多其他细节和安全问题没有做过多处理,否则就喧宾夺主了。比如本文中所提到的线程执行函数,其实存在线程安全问题,而我又不想引入COM跨线程问题,所以就如此简单粗暴的编写。

STDMETHODIMP CTestEvent::FireEvent()
{HRESULT hr = WBEM_S_NO_ERROR;ATLASSERT(m_pEventClass);CComPtr<IWbemClassObject> pInstance;hr = m_pEventClass->SpawnInstance(0, &pInstance);if(FAILED(hr)) {return hr;}CComVariant value;value.vt = VT_BSTR;value.bstrVal = CComBSTR("notepad.exe");pInstance->Put(L"name", 0, &value, 0);return m_pSink->Indicate(1, &(pInstance.p) );
}

我们Spawn一个实例,然后填充它的一些属性,最后将该对象放入客户端可以访问的sink中。
        我们使用之前实现的查询类查询该事件

    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);CAsynNotifyQuery<CInstanceEvent> recvnotify(L"root\\default", L"SELECT * FROM ClassEventInstance", hEvent);recvnotify.ExcuteFun();

我们即可以看到结果

extrinsic event provider

extrinsic event provider实现讲完了,我们再讲讲intrinsic event provider。工程向导方面和extrinsic event provider基本相同,只是在WMI Class页中选择intrinsic event。我们对新的provider取名为IntrinsicEvent。我们也从mof入手,看看怎么修改

[
dynamic : ToInstance,
provider("IntrinsicEvent") : ToInstance, // uses the TestInstance Provider
ClassContext("whatever!"),          // information is dynamically// supported by the provider
DisplayName("IntrinsicClassInstance"): ToInstance
]                                    class IntrinsicClassInstance
{
[key]
string name = "CIN";
[PropertyContext("IntrinsicClassInstance_Member")]
string value = "CIV";
};

首先我们定义Event的类名——IntrinsicClassInstance,并申明其有两个属性——name和value。其次我们我们修改下事件提供者注册对象

instance of __EventProviderRegistration
{provider = $IntrinsicEvent;EventQueryList = {"select * from __InstanceCreationEvent where TargetInstance isa \"IntrinsicClassInstance\""};
}; 

从WQL的写法我们可以发现,这种写法和检测进程创建的Win32_Process类类似,这就是内部(Intrinsic)事件的特点。cpp的修改和extrinsic event provider中介绍的过程类似,只是Intrinsic没有FireEvent方法,那我们就自己申明和定义一个

STDMETHODIMP CIntrinsicEvent::FireEvent()
{HRESULT hr = WBEM_S_NO_ERROR;ATLASSERT(m_pEventClass);CComPtr<IWbemClassObject> pInstance;hr = m_pDataClass->SpawnInstance(0, &pInstance);if(FAILED(hr)) {OutputTrace("CIntrinsicEvent::FireEvent1");return hr;}CComVariant value;value.vt = VT_BSTR;value.bstrVal = CComBSTR("notepad.exe");pInstance->Put(L"name", 0, &value, 0);CComPtr<IWbemClassObject> pEventInstance;hr = m_pEventClass->SpawnInstance(0, &pEventInstance);if(FAILED(hr)) {return hr;}CComVariant varTargetInst(pInstance);pEventInstance->Put(L"TargetInstance", 0, &varTargetInst, 0);return m_pSink->Indicate(1, &(pEventInstance.p) );
}

我们将新生成的实例放入到pEventInstance实例的"TargetInstance"中,这也和上面的WQL的“TargetInstance isa \"IntrinsicClassInstance\"”相对应。pEventInstance实例的类是我们在模板基础上新增的,我们要修改Initialize函数,新增

hr = m_pNamespace->GetObject(CComBSTR("__InstanceCreationEvent"), 0, pCtx, //passing IWbemContext pointer to prevent deadlocks&m_pEventClass, NULL);
if (FAILED(hr)) {return hr;
}

我们使用如下代码访问该事件

    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);CAsynNotifyQuery<CInstanceEvent> recvnotify(L"root\\default", L"SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'IntrinsicClassInstance'", hEvent);recvnotify.ExcuteFun();

我们可以得到如下结果


        工程链接:http://pan.baidu.com/s/1o6QcgPW 密码:4l5v

WMI技术介绍和应用——Event Provider相关推荐

  1. WMI技术介绍和应用——Event Consumer Provider

    在<WMI技术介绍和应用--Event Provider>和<WMI技术介绍和应用--接收事件>中,我们展现了如何处理和事件相关的WMI知识.而<WMI技术介绍和应用-- ...

  2. WMI技术介绍和应用——总结(完)

    断断续续的,历经三年将WMI这个主题给写完了.记得最开始时接触该技术,是因为传统获取CPU序列号的方法总是出错.于是接触了这种已经很老的技术.本着打破砂锅问到底的想法,我决定稍微研究一下,结果越来越深 ...

  3. WMI技术介绍和应用——Instance/Method Provider

    在<WMI技术介绍和应用--事件通知>一文中,我们提到了提供者(Provider)这个概念.我们还是要引入WMI的结构图(转载请指明出于breaksoftware的csdn博客) 我们在1 ...

  4. WMI技术介绍和应用——事件通知

    在<WMI技术介绍和应用--WMI概述>中,我们使用了下图介绍WMI构架(转载请指明出于breaksoftware的csdn博客) 我们之前介绍的使用WMI查询系统.硬件等信息的功能,是通 ...

  5. WMI技术介绍和应用——执行方法

    在之前的博文中,我们主要介绍了如何使用WMI查询信息和接收事件.本文将介绍WMI的另一种用法--执行方法.(转载请指明出于breaksoftware的csdn博客) 这块的内容在msdn中有详细的介绍 ...

  6. WMI技术介绍和应用——接收事件

    时隔两三年,再次更新WMI系列博文.好在功能在三年前就已经实现了,现在只要补充些实例即可. 之前介绍的基本都是查询静态数据,而本文将要介绍非常有意思的事件接收功能.(转载请指明出于breaksoftw ...

  7. WMI技术介绍和应用——查询硬件信息

    这个月实在太忙了,一直没有时间去继续写WMI的应用例子. 本来是希望将<WMI技术介绍和应用>系列博文写的像WMI百科全书般,但是貌似对这个技术感兴趣的同学并不多,所以我决定对部分知识点点 ...

  8. WMI技术介绍和应用——查询本地用户和组

    本文使用了< WMI技术介绍和应用--使用VC编写一个半同步查询WMI服务的类>中代码做为基础.本节只是列出了WQL语句,具体使用参看前面的例子.( 转载请指明出于breaksoftwar ...

  9. WMI技术介绍和应用——查询系统服务

    本文使用了< WMI技术介绍和应用--使用VC编写一个半同步查询WMI服务的类>中代码做为基础.本节只是列出了WQL语句,具体使用参看前面的例子.( 转载请指明出于breaksoftwar ...

最新文章

  1. 这个神奇的网站提供各种图的代码供您参考!
  2. java 重写set方法_Java程序设计-方法的重写(override)(笔记)
  3. python提取abaqus数据_Python语言在ABAQUS数据提取中的简单应用
  4. 【Redis学习】Transaction事务管理
  5. 丢失api-ms-win-crt-runtime-l1-1-0.dll
  6. leetcode 402. 移掉K位数字(贪心算法)
  7. 蠕变断裂 ansys_如何避免范围蠕变,以及其他软件设计课程的辛苦学习方法
  8. java之备忘录模式,java设计模式之备忘录模式
  9. 网络_远程开机(ubuntu)
  10. c#程序设计语言杜松江版_C#程序设计语言复习题(试题及答案版)
  11. 电脑公司最新稳定win7系统下载
  12. 龙芯CPU芯片架构分析
  13. 利用pyboardCN V2播放Bad apple
  14. 饿了么4年 + 阿里2年:研发路上的一些总结与思考
  15. anaconda 安装 TensorFlow 过程记录
  16. 最新会声会影2023旗舰版更新了哪些功能?
  17. 3D变电站园区3D可视化电力监控管理平台
  18. 打光在绘画中的重要性有多重要?
  19. myrio与fpga编程_myRIO入门实验指导书
  20. C语言实现,一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?

热门文章

  1. OpenCV中的尺度不变特征变换(SIFT Scale-Invariant Feature Transform)
  2. 深蓝学院第二章:基于全连接神经网络(FCNN)的手写数字识别
  3. GitHub开源的最全中文诗歌古典文集数据库
  4. 基于颜色特征,形状特征和纹理特征的数字图像的检索(Digital Image Retrieval)MATLAB GUI实现
  5. Qt开发环境的下载地址
  6. POJ - 3417 Network LCA+树上差分
  7. POJ - 1986 Distance Queries 倍增求LCA
  8. LeetCode刷题记录2——217. Contains Duplicate(easy)
  9. ATS 6.2.1打release版本rpm包时插件中出现undefined symbol的问题追踪
  10. python-eggs异常解决方法