Windows Management Instrumentation
システム情報を収集するライブラリを作りたくでWMIを使おうとしてるんですが、呼び出しの手順とかデータの取得手順が面倒なんで、WMIを処理するクラスを作ってみました。
今日はaccessした結果の行情報を表示するまでのところです。
wmi.hファイル
class WmiCall { public: WmiCall(); WmiCall(const WmiCall& from); ~WmiCall(); bool init(); void term(); IEnumWbemClassObject *access(String select_stmt); String getErrorMessage(); private: IWbemLocator *pLoc; IWbemServices *pSvc; HRESULT hRes; int errPos; }; // WmiCall
wmi.cppファイル
// Constructor WmiCall::WmiCall() { pLoc = NULL; pSvc = NULL; hRes = S_OK; errPos = 0; } // Copy Constructor WmiCall::WmiCall(const WmiCall& from) { pLoc = from.pLoc; pSvc = from.pSvc; hRes = S_OK; errPos = 0; } // Destructor WmiCall::~WmiCall() { } /* * WMI呼び出しの初期化を行う * param : 無し * * return : bool * true = 初期化が成功した * false = 初期化に失敗した */ bool WmiCall::init() { /* * COMライブラリの初期化 * return : S_OK = 正常に初期化できた * S_FALSE = 実行Thread内で既に初期化されていた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms695279(VS.85).aspx */ hRes = CoInitializeEx(0, COINIT_MULTITHREADED); if ((hRes != S_OK) && (hRes != S_FALSE)) { errPos = 1; return false; } /* * セキュリティ関連情報の登録 * return : S_OK = 正常に登録できた * RPC_E_TOO_LATE = 実行Process内で既に登録されていた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms693736(VS.85).aspx */ hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); if ((hRes != S_OK) && (hRes != RPC_E_TOO_LATE)) { errPos = 2; CoUninitialize(); return false; } /* * 初期化されていないCLSIDに連携するオブジェクトを生成する * return : S_OK = 正常に生成できた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms686615(VS.85).aspx */ if (pLoc == NULL) { hRes = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc); if (hRes != S_OK) { errPos = 3; CoUninitialize(); return false; } } /* * ターゲットのマシンへ接続する * return : WBEM_S_NO_ERROR = 正常に接続できた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa391769(VS.85).aspx */ if (pSvc == NULL) { hRes = pLoc->ConnectServer(localHost, NULL, NULL, 0, NULL, 0, 0, &pSvc); if (hRes != WBEM_S_NO_ERROR) { errPos = 4; pLoc->Release(); pLoc = NULL; pSvc = NULL; CoUninitialize(); return false; } } return true; } /* * WMI呼び出しを完了する * param : 無し * * return : 無し */ void WmiCall::term() { if (pSvc != NULL) pSvc->Release(); if (pLoc != NULL) pLoc->Release(); /* * COMライブラリの開放 * 参照:http://msdn.microsoft.com/en-us/library/ms688715(VS.85).aspx */ CoUninitialize(); } /* * WQLを実行し結果セットを取得する * param : 実行するWQL文(String) * * return : IEnumWbemClassObjectポインター */ IEnumWbemClassObject *WmiCall::access(String select_stmt) { IEnumWbemClassObject *pEnumerator = NULL; if (pSvc != NULL) { /* * Queryの実行 * return : WBEM_S_NO_ERROR = 正常にQueryできた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa392107(VS.85).aspx */ hRes = pSvc->ExecQuery(WQL, bstr_t(select_stmt.c_str()), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_ENSURE_LOCATABLE, NULL, &pEnumerator); if (hRes != WBEM_S_NO_ERROR) { pEnumerator = NULL; errPos = 5; } } else { errPos = 6; hRes = WBEM_E_FAILED; } return pEnumerator; } /* * 各種APIを実行した結果のエラー文字列を取得する * param : 無し * * return : String */ String WmiCall::getErrorMessage() { basic_stringstream<TCHAR> buf; buf << msgTable[errPos]; buf << _T(" : ErrorCode = "); buf << uppercase << hex << hRes; return buf.str(); }
呼出プログラム
sysinfo.cpp
#include <windows.h> #include <string> #include <iostream> #include <sstream> using namespace std; #include <wmi.h> WmiCall wmi; void WIN32_OperatingSystem() { IEnumWbemClassObject *pEnumerator = wmi.access(_T("SELECT * FROM Win32_OperatingSystem")); if (pEnumerator == NULL) { String msg = wmi.getErrorMessage(); wout << msg; return; } _TCHAR **names = NULL; int row_pos = 0; long lb = 0, ub = 0; ULONG uReturn = 0; IWbemClassObject *pclsObj[1]; HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, pclsObj, &uReturn); if(hr == WBEM_S_NO_ERROR) { if (row_pos == 0) { int col_pos = 0; SAFEARRAY *pstrNames = NULL; hr = pclsObj[0]->GetNames(NULL, WBEM_FLAG_ALWAYS, NULL, &pstrNames); SafeArrayGetLBound(pstrNames, 1, &lb); SafeArrayGetUBound(pstrNames, 1, &ub); SafeArrayAccessData(pstrNames, (void **)&names); for (int i = lb; i <= ub; i++) { wstring name = wstring(names[i]); wout << name << endl; } SafeArrayUnaccessData(pstrNames); SafeArrayDestroy(pstrNames); } } } int _tmain(int argc, _TCHAR* argv[]) { if (wmi.init()) { WIN32_OperatingSystem(); wmi.term(); } return 0; }