使用WMI讀寫bios信息

雖然VBScript等腳本語言實現WMI編程更加方便,但有些時候我們還是不得不使用C++來編程,比如說要追求更好的性能或者是一個基於C++的項目中需要這樣的功能等等。
 
下面是用C++實現WMI編程的基本步驟,在這裏,我們通過讀取BIOS信息來演示如何實現。可以對照參考:
 
1.初始化COM
WMI提供的API是基於COM的,所以必須首先執行CoInitializeEx CoInitializeSecurity函數,以便訪問WMI
 
這裏需要如下定義和頭文件:
#define _WIN32_DCOM
#include <windows.h>
 
#include <comdef.h>
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
 
#include <iostream>
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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章