WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
在《WMI技术介绍和应用——VC开发WMI应用的基本步骤》文中,我们介绍了VC使用WMI技术的基本框架。本节我将讲解封装和实现一个用于半同步查询WMI的类。(转载请指明出于breaksoftware的csdn博客)
我曾思考过如何编写一个比较有用的类,因为不同平台上WMI的查询结果集是不同的,很难做个通用的类。于是,我使用了最简单的方法——遍历返回结果。我们先看下类的声明
class CSynQuery : public CWMI
{
public:CSynQuery(const wstring& wszNamespace, const wstring& wszWQLQuery);~CSynQuery(void);
private:HRESULT Excute(CComPtr<IWbemServices> pSvc);HRESULT DealWithIWbemClassObject(CComPtr<IWbemClassObject> pclsObj);virtual HRESULT DealWithSingleItem( CComBSTR bstrName, CComVariant Value, CIMTYPE type, LONG lFlavor );
private:wstring m_wszWQLQuery;
};
Excute是继承于CWMI基类中的纯虚函数。在CSynQuery实现的Excute中,我将执行一次半同步查询,并枚举返回的结果。
HRESULT CSynQuery::Excute( CComPtr<IWbemServices> pSvc )
{HRESULT hr = WBEM_S_FALSE;do {CComPtr<IEnumWbemClassObject> pEnumerator = NULL;hr = pSvc->ExecQuery( CComBSTR("WQL"),CComBSTR(m_wszWQLQuery.c_str()),WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumerator );CHECKWMIHR(hr);ULONG uReturn = 0;while (pEnumerator) {CComPtr<IWbemClassObject> pclsObj = NULL;HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);if ( 0 == uReturn) {break;}DealWithIWbemClassObject(pclsObj);}} while (0);return hr;
}
首先我们先看一下用于(半)同步查询的函数ExecQuery的声明
HRESULT ExecQuery([in] const BSTR strQueryLanguage,[in] const BSTR strQuery,[in] LONG lFlags,[in] IWbemContext *pCtx,[out] IEnumWbemClassObject **ppEnum
);
strQueryLanguage是用于标记查询的语言种类。由此参数可以发现,当初微软设计这个接口时是希望未来它支持更多的查询语言。由于目前只支持WQL语言,所以该参数只能传“WQL”。第二个参数strQuery是实际用于查询的命令,比如“Select * From XXX",是不是看着很像SQL?第三个参数lFlags是一个非常重要的参数,如果仔细看该文标题,可以发现,我用的是”半同步“而不是“同步”,该参数就控制着该函数到底是“同步”还是“半同步”。如果该参数包含WBEM_FLAG_RETURN_IMMEDIATELY,则说明该调用是个半同步调用,否则是同步调用。
现在我说一下WMI中同步和半同步两者的区别。同步这个过程不难理解,如果我们同步调用一个函数,该函数会经过计算后将返回结果准备好,然后返回到调用处。如果该过程非常消耗时间,且返回的结果非常占用空间,比如返回10240个对象,是不是觉得这个调用过程非常笨重?是的!那么解决这个问题的很好的方法便诞生了:半同步。半同步的调用方式非常类似于异步(以后介绍)调用。当我们调用一个半同步操作后,函数内部会启动线程去执行查询工作,之后会立即返回到我们的调用处。当半同步内部线程查询到并封装完一个对象后,便会通知我们外面枚举结果的函数,告诉我们:一个结果准备好了,你可以使用了。这个相当于将合并结果集的过程去掉。考虑到调用半同步的逻辑处理一个返回对象可能需要一定的时间,在半同步启动的线程中可以利用这段时间完成下一个对象的查找和封装。所以总体来说半同步对时间的消耗是比同步好的。而从占用资源的角度看,半同步不用一次返回那么多个结果,所以占用的资源会比同步方式好很多。所以大部分情况下,只在同步和半同步中做出选择的情况下,优先考虑使用半同步。
回到ExecQuery这个函数,lFlags还有个非常重要的可选值是WBEM_FLAG_FORWARD_ONLY。该参数让ExecQuery函数返回的枚举是个Forward-Only的。这样做的好处是可以让我们程序更快且占用更少的资源。所以lFlags一般是WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY。
pCtx一般设置为NULL。ppEnum是个返回结果的枚举器。
ULONG uReturn = 0;while (pEnumerator) {CComPtr<IWbemClassObject> pclsObj = NULL;HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);if ( 0 == uReturn) {break;}DealWithIWbemClassObject(pclsObj);}
我们可以如此枚举返回的结果集。关注一下Next第一参数。在之前对半同步的介绍中,我们说道:半同步函数启动的线程需要查询和封装下一个结果,其实这个可以看成是个异步操作,于是枚举结果这边需要等待那个实际查询的线程完成一个结果。我给此参数设置为“一直等待”。一般来说,这个结果是立即返回的。pclsObj保存的是一个结果集中的一个结果。我们使用DealWithIWbemClassObject函数处理每个结果。
HRESULT CSynQuery::DealWithIWbemClassObject( CComPtr<IWbemClassObject> pclsObj )
{HRESULT hr = WBEM_S_NO_ERROR; do {CComVariant vtClass; hr = pclsObj->Get(L"__CLASS", 0, &vtClass, NULL, NULL); CHECKWMIHR(hr);if ( VT_BSTR == vtClass.vt ) {wprintf(L"\n%s\n", vtClass.bstrVal);}hr = pclsObj->BeginEnumeration(WBEM_FLAG_LOCAL_ONLY);do {CComBSTR bstrName;CComVariant Value;CIMTYPE type;LONG lFlavor = 0;hr = pclsObj->Next(0, &bstrName, &Value, &type, &lFlavor);CHECKWMIHR(hr);hr = DealWithSingleItem(bstrName, Value, type, lFlavor); }while ( WBEM_S_NO_ERROR == hr );hr = pclsObj->EndEnumeration();} while (0);return hr;
}
该函数首先会打印出该结果属于哪个WMI类,然后会枚举结果中的每个成员。其实在实际使用中大可不必如此,我如此设计只是为了该例子可以在不同平台上,针对不同需求都可以正确执行。需要注意的一点是在枚举前,我们需要制定要枚举什么。于是我们要调用BeginEnumeration,并传WBEM_FLAG_LOCAL_ONLY,即枚举该类自己的成员。在枚举完之后,一般要调用EndEnumeration。其实这个不是必须的,只有在要提前退出枚举的场景下才必须调用EndEnumeration。针对每个成员,我们又要使用虚函数DealWithSingleItem来处理。于是处理逻辑又被我封装到一个继承于CSynQuery的类CSynQueryData中。该类逻辑非常简单,如果成员是非对象,则直接打印出来;如果结果是一个对象,则再解析这个对象,并将其中非对象打印出来。
HRESULT CSynQueryData::DealWithSingleItem( CComBSTR bstrName, CComVariant Value, CIMTYPE type, LONG lFlavor )
{HRESULT hr = WBEM_S_NO_ERROR; switch ( Value.vt ) {case VT_UNKNOWN : {DealWithUnknownTypeItem(bstrName, Value, type, lFlavor);}break;default: {PrintfItem(bstrName, Value, type, lFlavor);};}return hr;
}HRESULT CSynQueryData::DealWithUnknownTypeItem( CComBSTR bstrName, CComVariant Value, CIMTYPE type, LONG lFlavor )
{HRESULT hr = WBEM_S_NO_ERROR;if ( NULL == Value.punkVal ) {return hr;}// object类型转换成IWbemClassObject接口指针,通过该指针枚举其他属性CComPtr<IWbemClassObject> pObjInstance = (IWbemClassObject*)Value.punkVal;hr = pObjInstance->BeginEnumeration(WBEM_FLAG_LOCAL_ONLY);do {CHECKHR(hr);CComBSTR bstrNewName;CComVariant NewValue;CIMTYPE newtype;LONG lnewFlavor = 0;hr = pObjInstance->Next(0, &bstrNewName, &NewValue, &newtype, &lnewFlavor);CHECKHR(hr);PrintfItem(bstrNewName, NewValue, newtype, lnewFlavor);}while ( WBEM_S_NO_ERROR == hr );hr = pObjInstance->EndEnumeration();return WBEM_S_NO_ERROR;
}VOID CSynQueryData::PrintfItem( CComBSTR bstrName, CComVariant Value, CIMTYPE type, LONG lFlavor )
{wprintf(L"%s\t",bstrName.m_str);switch ( Value.vt ){case VT_BSTR: {wprintf(L"%s",Value.bstrVal); }break;case VT_I1:case VT_I2:case VT_I4:case VT_I8: case VT_INT: {wprintf(L"%d",Value.intVal); }break;case VT_UI8:case VT_UI1: case VT_UI2:case VT_UI4:case VT_UINT:{wprintf(L"0x%u",Value.intVal); }break;case VT_BOOL:{wprintf(L"%s", Value.boolVal ? L"TRUE" : L"FASLE" );}break;default:{ATLASSERT(FALSE);};}wprintf(L"\n");
}
至此,一个半同步查询的框架就搭建完成。我会之后若干节,结合实际应用场景,利用这个框架,讲解WMI的实际应用。
工程源码见《WMI技术介绍和应用——WMI概述》结尾。
相关文章:

致被套基民:老基民的四点教训七点经验(ZT)
四点错误: 一是没有足够的耐心。比如我曾买入一只基金,上半年表现不好,在忍无可忍之下终于赎回,结果它在下半年股市调整时大放异彩,成为收益率的冠军; 二是只看高分红买基金,结果错过了几只净值…
千万用户同时在线,优酷智能档在双11“猫晚”直播如何防卡顿?
作者 | 阿里文娱高级技术专家肖文良出品 | AI科技大本营(ID:rgznai100) 导读:本文为阿里文娱高级技术专家肖文良在【阿里文娱2019双11猫晚技术沙龙】中的演讲,主要内容为如何通过优酷智能档,降低用户卡顿尤其是双11直播…

导航菜单:jQuery粘性滚动导航栏效果
粘性滚动是当导航在滚动过程中会占粘于浏览器上,达到方便网站页面浏览的效果,也是一种用户体验,下面我们看一下是怎么实现的: jQuery的 smint插件,也是一个导航菜单固定插件。当页滚动时,导航菜单会固定在顶…
如何用Python实现超级玛丽的人物行走和碰撞检测?
作者 | marble_xu编辑 | 郭芮出品 | CSDN博客在《如何用 Python 实现超级玛丽的界面和状态机?》这篇文章中我们讲解如何用代码实现界面和状态机,本文详解人物行走和碰撞检测的实现。功能介绍人物行走人物的行走速度这边分成水平方向(X轴&…

WMI技术介绍和应用——查询正在运行的进程信息
在《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》一文中,我们介绍到了一个半同步查询WMI类的框架。本文将是该技术的一个应用,介绍如何使用WMI技术查询正在运行的进程信息。(转载请指明出于breaksoftware的csdn博客ÿ…

20个经典要诀学好英语
出处:我学网互助论坛第一要诀:收听英语气象报告 有些教学录音带为配合初学者的学习,故意放慢语速,这对英语听力的训练是不够的。如果听语速正常的英语,初学者又会感到力不从心。英语气象报告的速度虽快,…

ArduinoYun教程之通过网络为Arduino Yun编程
ArduinoYun教程之通过网络为Arduino Yun编程 Arduino Yun的软件部分 通过第一章的介绍后读者就明白了Arduino Yun除了是一个类似其他Arduino的单片机之外,它的另一大组成部分就是运行着一个特殊Linux发行版的Atheros AR9331芯片。所以,本章将会介绍Ather…

WMI技术介绍和应用——查询正在运行的线程信息
本文使用了《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》中代码做为基础。 一般来说,如果试图枚举系统中的线程。需要先枚举系统中的进程,然后再枚举每个进程中的线程。而WMI给我们提供了一种比较简便的枚举线程信息的方法。࿰…
开源生态也难逃“卡脖子”危机?中国AI开发者的警醒和突围
开源不是一个新名词,也不是一个新行动。软件时代,开源推动了全球范围的创新技术成果落地,从而促进全球信息技术发生了全局性、持续性的重大变革,这使它甚至成为一条非常关键且成功的技术路线。随着AI时代的来临,阿里、…

Linux下应用软件的安装
对于刚刚接触Linux的朋友来说,安装一些应用软件是一件头疼的事,因为在Linux下安装应用软件和Windows下截然不同的,下面介绍一下Linux下安装应用软件来解决刚刚接触Linux而不会安装软件朋友的困惑.Linux下软件包有两种比较常见的形式,一种是以 RPM、deb包为代表的智能…

Hibernate 的 session.load()使用方法
2019独角兽企业重金招聘Python工程师标准>>> protected Person getOne(int id){ Session session HibernateSessionFactory.getSession(); Person person new Person(); try{ session.load(person, id); }catch(Exception e){ e.printStackTrace(); }final…

WMI技术介绍和应用——查询桌面信息
本文使用了《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》中代码做为基础。 在Windows操作系统中,存在很多Windows Station。而每一个Windows Station又存在一个或者多个Windows Desktop。我们一般所说的桌面只是这些众多桌面中的一个。以下内容将介…
联泰集群发布水晶系列工作站,用于深度学习场景
北京时间2019年12月26日,联泰集群在北京正式发布了水晶系列工作站产品 W722、W7224和W5232。 联泰集群硬件产品技术中心总监刘振锋、软件产品技术中心总监孙建军、硬件产品技术中心工程师肖学文分别从应用方向、水晶工作站一体化软件平台及水晶系列产品硬件方面对本…

航空黑客私人YY
坐飞机从从云南飞回老家广州~~~当然绝对支持深圳航空啦!嘎嘎!为啥?当然是服务好 MM太PL了!呵呵!而且在看杂志的同时还看到了一则新闻 内容如下 近日,深圳航空公司与瑞士OnAir公司在香港签约,合作推动在飞机上实现万米高空的自由通信。2008年奥运会前&am…

Redis安装整理(window平台) +php扩展redis
window平台Redis安装 redis windows安装文件下载地址:http://code.google.com/p/servicestack/wiki/RedisWindowsDownload#Download_32bit_Cygwin_builds_for_Windows我选择的redis为最新版的安装文件,见下图: Redis安装文件解压后,有以下…

WMI技术介绍和应用——查询环境变量
本文使用了《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》中代码做为基础。 我们可以通过系统属性查看当前系统和当前用户的环境变量。(转载请指明出于breaksoftware的csdn博客) 如何使用WMI枚举所有环境变量的信息? CSynQue…
想学新的编程语言?考虑下Go吧
作者 | Lewis Fairweather译者 | 弯月,责编 | Elle来源 | CSDN(ID:CSDNnews)【导读】快速的运行时、高效的并发、简单易学的语法,这些都是Go语言最吸引人的特性。以下为译文:Go语言的入门门槛之低令我感到惊…

oracle学习总结三(bulk collect用法)
通过bulk collect减少loop处理的开销发表人:logzgh | 发表时间: 2006年五月19日, 10:56采用bulk collect可以将查询结果一次性地加载到collections中。而不是通过cursor一条一条地处理。可以在select into,fetch into,returning into语句使用bulk collect。注意在使用bulk coll…

MQTT的学习研究(五) MQTT moquette 的 Blocking API 发布消息服务端使用
参看官方文档: http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/index.jsp?topic/com.ibm.mq.amqtat.doc/tt00000_.htm * Java 为 MQ Telemetry Transport 创建异步发布程序 *在此任务中,您将遵循教程来修改第一个发布程序。通过修改,…

WMI技术介绍和应用——查询驱动信息
本文使用了《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》中代码做为基础。 如何使用WMI查询所有驱动信息?(转载请指明出于breaksoftware的csdn博客) CSynQueryData recvnotify(L"root\\CIMV2",L"SELECT * FR…

NumericUpDown
NumericUpDown控件主要功能是为一个TextBox控件添加上下按钮,当单击按钮时实现数字的加减,同时也可以提供静态数据,实现这些数据的上下选择。 属性列表: TargetControlID:该控件的目标作用控件。 Width&…
提高建模效率,改变手工作坊式生产,AutoML的技术研究与应用进展如何了?
整理 | 王银出品 | AI科技大本营(ID:rgznai100)【导读】12 月 5-7 日,由中国计算机学会主办,CCF 大数据专家委员会承办,CSDN、中科天玑协办的中国大数据技术大会(BDTC 2019)在北京长城饭店隆重举…

.net使用memcached
Windows中memached安装 -------------服务器端配置 1>开始>运行:CMD(确定) 2>cd C:\memcached(回车) 3>memcached -d install(回车 这步执行安装) 4>memcached -d start(回车 这步执行启动memcache服务器,默认分配64M内存&…
22张精炼图笔记,深度学习专项学习必备
作者 | DL&CV_study9编辑 | Elle来源 | CSDN 博客本文为人工智能学习笔记记录。【深度学习基础篇】一、深度学习基本概念监督学习:所有输入数据都有确定的对应输出数据,在各种网络架构中,输入数据和输出数据的节点层都位于网络的两端&…

WMI技术介绍和应用——查询文件夹信息
本文使用了《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》中代码做为基础。本节只是列出了WQL语句,具体使用参看前面的例子。 本节主要介绍Win32_Directory类。通过该类我们将可以获得部分常用的文件夹信息。在该类中,有属性Name&#x…

CSLA .NET概述
CSLA是Component-based, Scalable, Logical Architecture的简写,CSLA .NET是Rockford Lhotka基于.Net设计的一套N-tier分布式框架。 CSLA .NET包含如下功能: l n-Level undo capability 译:n层撤销功能 l Tracking broke…

简短的几句js实现css压缩和反压缩功能
写在前面 最近一直在整理css,但因为现在Visual Studio 2013太智能了,它每每在我按ctrlED进行格式化代码的时候,就会将css进行层次格式化(如下图所示),而这个格式让我老大实在无法忍受,我老大认为…
迁移学习前沿研究亟需新鲜血液,深度学习理论不能掉链子
作者 | Frederico Guth,Tefilo Emidio de Campos编译 | 夕颜出品 | AI科技大本营(ID:rgznai100)【导读】人类可以从很少的样本中学习,显示出了人类卓越的泛化能力,而这一点学习算法仍远做不到。当前,最成功的模型需要大量标记好的…

WMI技术介绍和应用——查询磁盘分区和逻辑磁盘信息
本文使用了《WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类》中代码做为基础。本节只是列出了WQL语句,具体使用参看前面的例子。(转载请指明出于breaksoftware的csdn博客) 本节主要介绍Win32_DiskPartition和Win32_LogicalDisk两…

用 jQuery 的 AJAX 功能发现的一个错误/注意点:HTTP Error 411
今天程序中有个地方需要 Ajax 方式 POST 数据,发现在 IE 6.0 下正常,而 FireFox 2.0.0.9 下则出错。通过 FireBug 抓取 ajax 回发后得到的页面信息如下:HTTP Error 411 - Length required 经过 google 搜索发现,这个 HTTP 状态码对…