虽然
VBScript
等脚本语言实现
WMI
编程更加方便,但有些时候我们还是不得不使用
C++
来编程,比如说要追求更好的性能或者是一个基于
C++
的项目中需要这样的功能等等。
下面是用
C++
实现
WMI
编程的基本步骤,在这里,我们通过读取
BIOS
信息来演示如何实现。可以对照参考:
http://www.qingfengju.com/article.asp?id=60(
通过一个具体实例来理解WMI脚本编程-读取BIOS信息
)
。
1.初始化COM
WMI
提供的
API
是基于
COM
的,所以必须首先执行
CoInitializeEx
和
CoInitializeSecurity
函数,以便访问
WMI
。
这里需要如下定义和头文件:
#define
_WIN32_DCOM
#include
#include
#include
#pragma
comment(lib, "wbemuuid.lib")
#include
using
namespace std;
·用CoInitializeEx函数初始化COM接口:
HRESULT
hr= CoInitializeEx(0,COINIT_MULTITHREADED);
if
(FAILED(hr))
{
return FALSE;
}
注意这个
FAILED
的定义是:
#define
FAILED(hr) (((HRESULT)(hr)) < 0)
·用CoInitializeSecurity函数注册并设置进程的默认的安全值:
hr
=
CoInitializeSecurity(
NULL, // Security descriptor
-1, // COM negotiates authentication service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication level for proxies
RPC_C_IMP_LEVEL_IMPERSONATE,// Default Impersonation level for proxies
NULL, // Authentication info
EOAC_NONE, // Additional capabilities of the client or server
NULL); // Reserved
if
(FAILED(hr))
{
CoUninitialize();
return FALSE;
}
2.创建一个到WMI命名空间的连接
WMI
并不是运行在我们自己的进程中,需要在
WMI
和我们的程序中创建一个连接。
·用CoCreateInstance函数来初始化IwbemLocator接口
IWbemLocator
*pLoc = 0;
hr
= CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID *) &pLoc
);
if
(FAILED(hr))
{
CoUninitialize();
return FALSE;
}
·用IWbemLocator::ConnectServer方法连接到WMI
ConnectServer
方法返回一个
IWbemServices
接口的代理,可以用来访问本地或是远程
WMI
命名空间。
IWbemServices
*pSvc = 0;
hr
= pLoc->ConnectServer(
BSTR(L"root\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if
(FAILED(hr))
{
pLoc->Release();
CoUninitialize();
return FALSE;
}
3. 设置WMI连接的安全属性
因为
IWbemServices
代理允许使用进程外对象,但是在
COM
中,如果没有设置安全属性,是不允许进程间互相访问的。所以需要用
CoSetProxyBlanket
函数设置
IWbemServices
代理的安全值。
hr
= CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if
(FAILED(hr))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE;
}
4.执行自己需要的操作
WMI
通过
COM
提供了许多用来访问系统数据的接口,这里我们要读取系统的
BIOS
信息。
·用IWbemServices指针向WMI发送请求,获取Win32_BIOS类的实例集合
IEnumWbemClassObject
*
pEnumerator = NULL;
hr
= pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("Select * FROM Win32_BIOS"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if
(FAILED(hr))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE;
}
·遍历IEnumWbemClassObject,输出信息
IWbemClassObject
*pclsObj=NULL;
while
(pEnumerator)
{
ULONG uReturn = 0;
hr = pEnumerator->Next(
WBEM_INFINITE,
1,
&pclsObj,
&uReturn
);
if(0 == uReturn)
break;
VARIANT vtProp;
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
wcout << vtProp.bstrVal << endl;
hr = pclsObj->Get(L"Manufacturer", 0, &vtProp, 0, 0);
wcout << vtProp.bstrVal << endl;
hr = pclsObj->Get(L"Version", 0, &vtProp, 0, 0);
wcout << vtProp.bstrVal << endl;
hr = pclsObj->Get(L"CurrentLanguage", 0, &vtProp, 0, 0);
wcout << vtProp.bstrVal << endl;
VariantClear(&vtProp);
}
if
(pclsObj!=NULL){
pclsObj->Release();
}
if
(pEnumerator!=NULL){
pEnumerator->Release();
}
5.释放资源
pSvc
->
Release
();
pLoc
->
Release
();
CoUninitialize
()