WMI技术介绍和应用——事件通知
在《WMI技术介绍和应用——WMI概述》中,我们使用了下图介绍WMI构架(转载请指明出于breaksoftware的csdn博客)
我们之前介绍的使用WMI查询系统、硬件等信息的功能,是通过查询WMI静态数据的空间实现的。这个功能的核心是在上图中2,即WMI Infrastructure层实现的。本文将让我们对WMI的认识深入到1,即WMI Providers and Managed Objects层。具体的功能是使用WMI检测到WMI数据和服务的变化。再具体一点就是,我们可以使用WMI检测进程创建、服务状态变化、电脑状态变化,磁盘可用空间变化等信息。这些都是非常让人激动的技术,我想做过安全的朋友应该清楚,如果想全局监控系统中进程的创建,除了下驱动就是使用Hook技术。如果你只是想知道哪些进程创建这样轻量级的需求,也要使用驱动、Hook这种重量级的技术,是否感觉有点得不偿失?而WMI就给我们提供了这样的一种轻量级的解决方案。
上图的WMI Providers and Managed Objects(托管对象和WMI提供者)层中,我们将使用Provider帮我们检测WMI变化。需要注意的一点是,并不是所有的Provider都可以为我们提供事件通知——只有WMI Event Class的托管对象才会在事件发生时给我们提供通知。我们收到的事件,可能来源于两种事件,一种是intrinsic event,即内在事件;还有一种是extrinsic event,即外来事件。内在事件是在标准的WMI数据模型发生改变而产生的事件,这将是我们介绍的重点。外来事件,和内在事件相对,即非标准WMI数据数据模型发生改变而产生的事件。
介绍了这么多基础知识了,那如何查询事件通知呢?在《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》中,我们讲解WMI查询静态数据时,我们可以使用同步查询和半同步查询两种查询方式。像静态数据,正如其名,它是静态的,即它存在就存在,不存在即不存在,所以我们可以使用同步方式查询。半同步其实就是一个伪装的异步操作,我们在那篇文章中已经做了介绍,本文不再赘述。而本文主要讲解的查询事件通知,它是动态发生的。即可能我查询的即刻,那个事件还未发生,我们需要等待一段时间,才会在事件发生后接收到通知。这就意味着查询事件通知,是不可能使用同步查询方式,我们可以选择异步查询或者半同步查询方式。
作为查询的载体——事件使用者(Event Consumers),也是分为两种:临时事件使用者和永久事件使用者。
临时事件使用者是我们未来最早接触到的一个使用者,顾名思义,它是指WMI接收事件通知的生命周期和发起查询的应用程序一致。WMI包含一个统一的接口用来向客户端应用程序提供WMI事件。
永久事件使用者是一种更复杂的使用者——它是一个COM对象,用于持续接收WMI事件通知。它使用一些现有的对象和过滤器去获取WMI事件。我们可以设置一些WMI对象和过滤器去获取WMI事件。当一个事件发生,并命中过滤器,WMI将加载永久事件使用者并通知它某事件发生了。或许你会有点好奇,永久事件使用者是保存在什么地方?WMI又是如何找到它的?永久事件使用者是保存在WMI仓库中(上图2层中WMI repository),并且是一个在WMI中注册的可执行文件,这样WMI便可以方便的寻找和加载它了。
这些事件都是由事件提供者(An event provider)发送给WMI的。它也是个COM组件。我们可以使用C++或者C#编写事件提供者程序。大部分事件提供者管理着一个WMI对象。对于如何编写WMI事件提供者,我们会在之后介绍。
我们再回到查询事件通知,首先我们要编写一个异步事件查询类。因为连接空间等操作和之前的都相同,所以我们的查询类也是继承于《WMI技术介绍和应用——VC开发WMI应用的基本步骤》介绍的CWMI类
template<typename T>
class CAsynNotifyQuery : public CWMI
{
public:CAsynNotifyQuery(const wstring& wszNamespace, const wstring& wszWQLQuery, HANDLE hExitEvent);~CAsynNotifyQuery(void);
private:HRESULT Excute(CComPtr<IWbemServices> pSvc);
private:wstring m_wszWQLQuery;HANDLE m_hExitHandle;
};
CAsynNotifyQuery是一个模板类,这是区别于我们之前的其他类。我们再来关注下主要方法——Excute方法的实现template<typename T>
HRESULT CAsynNotifyQuery<T>::Excute( CComPtr<IWbemServices> pSvc )
{HRESULT hr = WBEM_S_FALSE;do {CComPtr<IUnsecuredApartment> pUnsecApp = NULL;hr = CoCreateInstance( CLSID_UnsecuredApartment, NULL,CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, (void**) &pUnsecApp);CHECKWMIHR(hr);CComPtr<IWbemObjectSink> pSink = new T;CComPtr<IUnknown> pStubUnk = NULL;pUnsecApp->CreateObjectStub(pSink, &pStubUnk);CComPtr<IWbemObjectSink> pStubSink = NULL;pStubUnk->QueryInterface(IID_IWbemObjectSink, (void**)&pStubSink);hr = pSvc->ExecNotificationQueryAsync( CComBSTR("WQL"),CComBSTR(m_wszWQLQuery.c_str()),WBEM_FLAG_SEND_STATUS,NULL,pStubSink );CHECKWMIHR(hr);if ( NULL != m_hExitHandle ) {WaitForSingleObject(m_hExitHandle, INFINITE );}hr = pSvc->CancelAsyncCall(pStubSink);if ( NULL != pSink ) {delete pSink;pSink = NULL;}} while (0);return hr;
}
首先我们需要创建一个IUnsecuredApartment接口实例。该接口是客户进程发起异步调用的,它提供了一个CreateObjectStub方法创建一个桩,WMI将在异步执行过程中对该桩进行操作。我们再看下传入的模板类的定义class CSink : public IWbemObjectSink
{
public:CSink();~CSink();virtual ULONG STDMETHODCALLTYPE AddRef();virtual ULONG STDMETHODCALLTYPE Release();virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);virtual HRESULT STDMETHODCALLTYPE Indicate(LONG lObjectCount, IWbemClassObject __RPC_FAR* __RPC_FAR* apObjArray);virtual HRESULT STDMETHODCALLTYPE SetStatus(LONG lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject __RPC_FAR* pObjParam);HRESULT DealIWbemClassObject(CComPtr<IWbemClassObject> pObj);
private:// 返回值为WBEM_S_NO_ERROR则继续枚举,否则中断枚举virtual HRESULT DealWithSingleItem(CComBSTR bstrName, CComVariant Value, CIMTYPE type, LONG lFlavor);
private:LONG m_lRef;bool m_bDone;
};
IWbemObjectSink接口用于接收WMI事件。我们主要需要实现Indicate方法,WMI框架将调用这个方法把消息实例传递给我们。从这个函数的最后一个参数可以看出,它传递过来的是一个事件数组HRESULT STDMETHODCALLTYPE CSink::Indicate( LONG lObjectCount, IWbemClassObject __RPC_FAR* __RPC_FAR* apObjArray )
{for (long i = 0; i < lObjectCount; i++) { CComPtr<IWbemClassObject> pObj = apObjArray[i]; DealIWbemClassObject(pObj);} return WBEM_NO_ERROR;
}
DealWbemClassObject是我自己定义和实现的方法,其主要功能就是输出事件的内容。 我们可以使用下例去调用查询操作
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);CAsynNotifyQuery<CInstanceEvent> recvnotify(L"root\\CIMV2", L"SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'", hEvent);recvnotify.ExcuteFun();
更多事件查询的例子,可以查看《WMI技术介绍和应用——接收事件》一文。
工程源码见《WMI技术介绍和应用——WMI概述》结尾。
相关文章:

OpenWebSpider 安装使用
OpenWebSpider 是一个很好用的网络爬虫,也可以叫做“网络蜘蛛”. 安装: 1.使用Vs.net 2003 编译, 记得要copy libmysql.dll到工程里 2.配置文件openwebspider.conf 将已经启动了的 mysql数据库用户名,密码填写好 3.数据库建立 执行 sql_struc…
杂谈 | 当前知识蒸馏与迁移学习有哪些可用的开源工具?
所有参与投票的 CSDN 用户都参加抽奖活动群内公布奖项,还有更多福利赠送作者&编辑 | 言有三来源 | 有三AI(ID:yanyousan_ai)【导读】知识蒸馏与迁移学习不仅仅属于模型优化的重要技术之一,也是提升模型跨领域泛化能力的重要技…

对 Thinking in java 4th Edition I/O DirList.java的疑问
2019独角兽企业重金招聘Python工程师标准>>> 以下原文代码: //: io/DirList.java // Display a directory listing using regular expressions. // {Args: "D.*\.java"} import java.util.regex.*; import java.io.*; import java.util.*; pub…

WMI技术介绍和应用——Instance/Method Provider
在《WMI技术介绍和应用——事件通知》一文中,我们提到了提供者(Provider)这个概念。我们还是要引入WMI的结构图(转载请指明出于breaksoftware的csdn博客) 我们在1这层的Native C/C里可以看到若干Provider,这…

SSH 组建轻量级架构 附录 -- 遇到的问题和解答
action: nulljava.lang.ClassNotFoundException: org.springframework.web.struts.ContextLoaderPlugIn解决方法:加载 spring.jar 包 报 无法初始化at org.apache.struts.action.ActionServlet.initModulePlugIns(解决方法:删除 asm-2.2.3.jar springda…
TIOBE 1月编程语言排行榜:C语言再度「C 位」出道,Python惜败
整理 | 屠敏来源 | CSDN(ID:CSDNnews)【导读】在 2020 年初雪来临之际,TIOBE 官方在最新发布的 1 月编程语言榜单中为我们最终揭开了「 2019 年度编程语言」的神秘面纱,然意料之外情理之中,获此殊荣的并非是…

my项目的总结2015.8.26编
这已经是上上个星期的事了,现在回顾一下: 负责的模块是"my",更精准的说应该是my里面的个人信息管理 由于项目分域,模块已经分好了,涉及到的只是在现有的基础上解决分域后遗留的历史问题 上点图吧:…
WMI技术介绍和应用——Event Provider
在《WMI技术介绍和应用——Instance/Method Provider》一文中,我们介绍了Instance和Method Provider的编写方法。本文我们将介绍更有意思的“事件提供者”。在《WMI技术介绍和应用——事件通知》中,我们曾经提到事件是分为两种:intrinsic eve…

Windows server 2003 IP路由配置
1、静态路由:在静态路由中必须明确指出从源到目标所经过的路径2、默认路由:默认路由是一种特殊的静态路由,为那些在路由表中没有找到明确匹配的路由信息的数据包指定下一步跳地址。在Windows server 2003的计算机上配置默认网关时就为该计算机…
人工智能的下一个前沿:识别“零”和“无”
所有参与投票的 CSDN 用户都参加抽奖活动群内公布奖项,还有更多福利赠送作者 | Max Versace译者 | 夕颜出品 | AI科技大本营(ID:rgznai100)声明:本文为客座文章,仅是为作者的观点,不代表 IEEE Spectrum 或 …

File Operations In Java
2019独角兽企业重金招聘Python工程师标准>>> The “File” class in Java defines many useful methods, here is a program which demonstrates some of these methods. import java.io.*;public class streams {public static void main(String []args){File f1ne…
Cascade RPN,结构的艺术带来极致提升 | NeurIPS 2019
作者 | VincentLee来源 | 晓飞的算法工程笔记(ID: gh_084c810bc839)导读:论文提出Cascade RPN算法来提升RPN模块的性能,该算法重点解决了RPN在迭代时anchor和feature不对齐的问题,论文创新点足,效果也很惊艳…

IIS+PHP+MySQL+Zend Optimizer+GD库+phpMyAdmin安装配置[完整修正实用版]
IISPHPMySQLZend OptimizerGD库phpMyAdmin安装配置[完整修正实用版]IISPHPMySQLZend OptimizerGD库phpMyAdmin安装配置[完整修正实用版][补充]关于参照本贴配置这使用中使用的相关问题请参考关于WIN主机下配置PHP的若干问题解决方案总结这个帖子尽量自行解决,谢谢[url]http://b…

WMI技术介绍和应用——Event Consumer Provider
在《WMI技术介绍和应用——Event Provider》和《WMI技术介绍和应用——接收事件》中,我们展现了如何处理和事件相关的WMI知识。而《WMI技术介绍和应用——接收事件》一文则主要讲解了如何查询事件,这种查询是在我们进程存在时发生的,一旦我们…

shell练习四
2019独角兽企业重金招聘Python工程师标准>>> 模拟linnux登录shell #!/bin/bash echo -n "login:" read name echo -n "passwd:" read passwdif [ $name"aaa" -a passwd"aaa" ]; thenecho "the host and passwd is rig…

WMI技术介绍和应用——总结(完)
断断续续的,历经三年将WMI这个主题给写完了。记得最开始时接触该技术,是因为传统获取CPU序列号的方法总是出错。于是接触了这种已经很老的技术。本着打破砂锅问到底的想法,我决定稍微研究一下,结果越来越深。正好借着年前这点时间…
2020年,大火的Python和JavaScript是否会被取而代之?
作者 | Richard Kenneth Eng 译者 | 明明如月,编辑 | 郭芮 来源 | CSDN(ID:CSDNnews) Python 和 JavaScript 是目前最火的两大编程语言。然而,他们不可能永远屹立不倒。最终,必将像其他编程语言一样跌下神坛…

WaveSwipeRefreshLayout
WaveSwipeRefreshLayout 介绍: 水滴效果的下拉刷新,效果非常不错。 http://itlanbao.com/code/20150815/10000/100423.html 运行效果: 相关代码 android Gallery 图片滚动 BalloonPerformerCountryRankDelightfulMenuDrawableFancyBackground…

Google Test(GTest)使用方法和源码解析——概况
GTest是很多开源工程的测试框架。虽然介绍它的博文非常多,但是我觉得可以深入到源码层来解析它的实现原理以及使用方法。这样我们不仅可以在开源工程中学习到实用知识,还能学习到一些思想和技巧。我觉得有时候思想和技巧是更重要的。(转载请指…
Reddit票选 | 2019年绝对不能错过的机器学习论文
来源 | reddit.com编辑 | 神经星星 神经小兮技术顾问 | 姜汉(openbayes.com)来源 | HyperAI超神经(ID:HyperAI)【导读】回顾 2019 年,人工智能领域时有大事发生,吸引着各界人士的关注。这一年,也…

ASP中的常用服务器检测源码
在写ASP网页时常用的检测代码:服务器现在时间: 引用<% now %>服务器CPU型号: 引用<%Request.ServerVariables("HTTP_UA_CPU")%>当前分辨率: 引用<% Request.ServerVariables("HTTP_UA_PIXELS")%>可显示颜色:[qoute]<%Request.ServerV…

选IDC房时,用脚本截取丢失包和rtt的值作比对
由于业务增长,需要选一个IDC房托管接入。网络质量要求比较高。在IDC给出测试机时,利用smokping来测试,是测出去的包。由于我们在各个地区都有接入机。再从这些接入机去测IDC网络质量,比对指标:丢失的包和rtt返回时延。…
Google Test(GTest)使用方法和源码解析——自动调度机制分析
在《Google Test(GTest)使用方法和源码解析——概况 》一文中,我们简单介绍了下GTest的使用和特性。从这篇博文开始,我们将深入代码,研究这些特性的实现。(转载请指明出于breaksoftware的csdn博客) 测试用例的自动保存…

D3D中简单的截图方法 (转)
【ZT】D3D中简单的截图方法 试了下,果然可以。在渲染完所有东东后(Present之前) 获得BackBuffer表面 然后用D3DX的函数保存 voidScreenShot (char*filename) { IDirect3DSurface9 *tmp NULL; IDirect3DSurface9 *back NULL; //生成固定…
2019年,自动化机器学习AutoML技术还火吗? | BDTC 2019
整理 | 王银出品 | AI科技大本营(ID:rgznai100) 【导读】12 月 5-7 日,由中国计算机学会主办,CCF 大数据专家委员会承办,CSDN、中科天玑协办的中国大数据技术大会(BDTC 2019)在北京长城饭店隆重…

第一次使用51cto博客
阿梅第一次使用51cto博客,以后将学习中的总结写到这里来。加油。转载于:https://blog.51cto.com/hopit/1690465

Google Test(GTest)使用方法和源码解析——结果统计机制分析
在分析源码之前,我们先看一个例子。以《Google Test(GTest)使用方法和源码解析——概况 》一文中最后一个实例代码为基准,修改最后一个“局部测试”结果为错误。(转载请指明出于breaksoftware的csdn博客) class ListTest : publi…
贾扬清感谢信:阿里开源10年,致敬千万开源人
整理 | 夕颜【导读】2019 年 10 月,有人曾根据 www.gharchive.org 的数据整理出一份 2019 年GitHub 开源贡献排行榜,获取 GitHub 2019 年的 PushEvent,通过分析 GitHub 用户提交记录中的邮件地址,分辨其所属组织。从这份榜单上可…

热烈庆祝我国神七发射成功!
热烈庆祝我国神七发射成功!
云计算设计模式(十)——守门员模式
云计算设计模式(十)——守门员模式 通过使用充当客户端和应用程序或服务之间的代理,验证和进行消毒的请求,并将它们之间的请求和数据的专用主机实例保护的应用程序和服务。这可以提供一个额外的安全层,并限制了系统的攻…