WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
来源:互联网 发布:家具甲醛标准 知乎 编辑:程序博客网 时间:2024/05/14 19:45
在《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;
- };
- 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
- );
现在我说一下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);
- }
- 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;
- }
- 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技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
- WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
- WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
- WMI技术介绍和应用——查询系统服务
- WMI技术介绍和应用——VC开发WMI应用的基本步骤
- WMI技术介绍和应用——VC开发WMI应用的基本步骤
- WMI技术介绍和应用——VC开发WMI应用的基本步骤
- 【C++码农】WMI技术介绍和应用——VC开发WMI应用的基本步骤
- WMI技术介绍和应用——WMI概述
- WMI技术介绍和应用——WMI概述
- WMI技术介绍和应用——WMI概述
- WMI技术介绍和应用——WMI概述
- WMI技术介绍和应用——查询桌面信息
- WMI技术介绍和应用——查询环境变量
- WMI技术介绍和应用——查询驱动信息
- WMI技术介绍和应用——查询文件夹信息
- WMI技术介绍和应用——查询系统信息
- WMI技术介绍和应用——查询时间信息
- JS通用校验-字段为空
- Lighting and environment mapping with GLSL
- poj 2431 Expedition
- UIO 子系统结构介绍
- unity3d学习笔记(十一)--NGUI结合Shader制作小地图
- WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
- ImportError:The _imagingft C module is not installed 错误的解决方法
- mysql 视图
- org.apache.avro.specific.SpecificDatumReader$SchemaConstructable
- JRE、JDK、IDE(Myeclipse)区别
- Android Boot loader
- Lua函数中的变长参数
- java get file contents
- Tomcat内存溢出的三种情况及解决办法分析