Windows Management Instrumentation (3)
前回作ったWmiResultクラスを整理してみました。
何となくさまになったかな・・・。
wmi.hのWmiResult定義を
typedef vector<long> long_vector; typedef vector<double> double_vector; typedef vector<bool> bool_vector; typedef vector<String> string_vector; typedef map<String, size_t> property_set; typedef property_set::iterator psIter; typedef property_set::const_iterator pscIter; typedef map<size_t, VARIANT> result_row; typedef result_row::iterator rrIter; typedef result_row::const_iterator rrcIter; typedef map<size_t, result_row> result_set; typedef result_set::iterator rsIter; typedef result_set::const_iterator rscIter; class WmiResult { public: WmiResult(); WmiResult(const WmiResult& from); ~WmiResult(); HRESULT loadProperties(IEnumWbemClassObject *pObjects); HRESULT loadValues(IEnumWbemClassObject *pObjects); size_t items(); size_t size(); string_vector getProperties(); String getProperty(size_t pos); result_set getResult(); VARIANT *getValue(String prop, size_t row); VARTYPE getValueType(String prop, size_t row); bool isArray(String prop, size_t row); long getLong(String prop, size_t row = 0, long deflong = 0); long_vector getLongArray(String prop, size_t row = 0, long deflong = 0); double getDouble(String prop, size_t row = 0, double defdouble = 0); double_vector getDoubleArray(String prop, size_t row = 0, double defdouble = 0); bool getBool(String prop, size_t row = 0, bool defbool = false); bool_vector getBoolArray(String prop, size_t row = 0, bool defbool = false); String getString(String prop, size_t row = 0); string_vector getStringArray(String prop, size_t row = 0); String print(); static VARTYPE getType(VARIANT *value); static bool isArray(VARIANT *value); static bool isByRef(VARIANT *value); static long getLong(VARIANT *value, long deflong = 0); static long_vector getLongArray(VARIANT *value, long deflong = 0); static double getDouble(VARIANT *value, double defdouble = 0); static double_vector getDoubleArray(VARIANT *value, double defdouble = 0); static bool getBool(VARIANT *value, bool defbool = false); static bool_vector getBoolArray(VARIANT *value, bool defbool = false); static String getString(VARIANT *value); static string_vector getStringArray(VARIANT *value); private: size_t rows; size_t cols; property_set properties; result_set results; };
に、
wmi.cppのWmiResultクラスの本体を
// Constructor WmiResult::WmiResult() { cols = 0; rows = 0; } // Copy Constructor /* * デフォルトのCopy Constructorでは、VARIANTのSAFEARRAYタイプのデータを * 正しくコピー出来ない為に作成 */ WmiResult::WmiResult(const WmiResult& from) { cols = from.cols; rows = from.rows; for (pscIter keys = from.properties.begin(); keys != from.properties.end(); keys++) { properties[keys->first] = keys->second; } VARIANT to_value; for (rscIter rs = from.results.begin(); rs != from.results.end(); rs++) { result_row to_row = result_row(); for (rrcIter rr = rs->second.begin(); rr != rs->second.end(); rr++) { /* * VARIANTデータエリアの初期化(初期化しておかないとVariantCopyの時にエリアを開放しようとしてエラーになる) * return : 無し * 参照:http://msdn.microsoft.com/en-us/library/ms221402.aspx */ VariantInit(&to_value); /* * VARIANTのデータをコピー * return : S_OK = 正常にコピーできた(ここでは結果はチェックしない) * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221697.aspx */ VariantCopy(&to_value, (VARIANT*)&rr->second); to_row[rr->first] = to_value; } results[rs->first] = to_row; } } // Destructor WmiResult::~WmiResult() { for (size_t i = 0; i < results.size(); i++) { rsIter rs = results.find(i); for (size_t j = 0; j < rs->second.size(); j++) { rrIter rr = rs->second.find(j); /* * VARIANTデータエリアのクリア * return : S_OK = 正常にクリアできた(ここでは結果はチェックしない) * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221165.aspx */ VariantClear(&rr->second); } rs->second.clear(); } results.clear(); properties.clear(); } /* * WMI呼び出しで戻ってきた結果セットからプロパティを保存する * param : 結果セット(IEnumWbemClassObjectポインター) * * return : HRESULT */ HRESULT WmiResult::loadProperties(IEnumWbemClassObject *pObjects) { HRESULT hRes; if (pObjects == NULL) { return WBEM_E_FAILED; } /* * 結果セットの現在行をリセットする * return : WBEM_S_NO_ERROR = 正常にResetできた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa390863(VS.85).aspx */ if ((hRes = pObjects->Reset()) == WBEM_S_NO_ERROR) { wchar_t **names = NULL; ULONG uReturn = 0; IWbemClassObject *pclsObj[1]; /* * 結果セットから現在行を取得し、行ポインターを次に進める * return : WBEM_S_NO_ERROR = 正常にNextできた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa390860(VS.85).aspx */ if ((hRes = pObjects->Next(WBEM_INFINITE, 1, pclsObj, &uReturn)) == WBEM_S_NO_ERROR) { SAFEARRAY *pstrNames = NULL; /* * 結果セットからプロパティの取得 * return : WBEM_S_NO_ERROR = 正常にGetNamesできた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa391447(VS.85).aspx */ if ((hRes = pclsObj[0]->GetNames(NULL, WBEM_FLAG_ALWAYS, NULL, &pstrNames)) == WBEM_S_NO_ERROR) { long lb = 0, ub = 0; BSTR name; /* * 配列エリアの開始位置の取得 * return : S_OK = 正常に取得できた(ここでは結果はチェックしない) * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221622.aspx */ SafeArrayGetLBound(pstrNames, 1, &lb); /* * 配列エリアの終了位置の取得 * return : S_OK = 正常に取得できた(ここでは結果はチェックしない) * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221584.aspx */ SafeArrayGetUBound(pstrNames, 1, &ub); for (long i = 0; i <= (ub - lb); i++) { /* * 配列エリア~指定の位置にあるデータを取得 * return : S_OK = 正常に取得できた(ここでは結果はチェックしない) * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221255.aspx */ SafeArrayGetElement(pstrNames, &i, (void*)&name); String prop = String((_TCHAR *)name); properties[prop] = cols++; } /* * 配列エリア~を開放する * return : S_OK = 正常に取得できた(ここでは結果はチェックしない) * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221702.aspx */ SafeArrayDestroy(pstrNames); } } } return hRes; } /* * WMI呼び出しで戻ってきた結果セットからデータを保存する * param : 結果セット(IEnumWbemClassObjectポインター) * * return : HRESULT */ HRESULT WmiResult::loadValues(IEnumWbemClassObject *pObjects) { HRESULT hRes; if (pObjects == NULL) { return WBEM_E_FAILED; } /* * 結果セットから現在行をリセットする * return : WBEM_S_NO_ERROR = 正常にResetできた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa390863(VS.85).aspx */ if ((hRes = pObjects->Reset()) == WBEM_S_NO_ERROR) { VARIANT vtProp, value; VariantInit(&vtProp); ULONG uReturn = 0; IWbemClassObject *pclsObj[1]; while (pObjects != NULL) { /* * 結果セットから現在行を取得し、行ポインターを次に進める * return : WBEM_S_NO_ERROR = 正常にNextできた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa390860(VS.85).aspx */ if(pObjects->Next(WBEM_INFINITE, 1, pclsObj, &uReturn) == WBEM_S_NO_ERROR) { result_row one_row = result_row(); for (psIter ps = properties.begin(); ps != properties.end(); ps++) { size_t col_pos = ps->second; _bstr_t key = bstr_t(ps->first.c_str()); /* * 結果セットからデータの取得 * return : WBEM_S_NO_ERROR = 正常にGetできた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/aa391442(VS.85).aspx */ if ((hRes = pclsObj[0]->Get(key, 0, &vtProp, 0, 0)) == WBEM_S_NO_ERROR) { VariantInit(&value); if (vtProp.vt != VT_NULL) { VariantCopy(&value, &vtProp); } one_row[col_pos] = value; } VariantClear(&vtProp); } results[rows++] = one_row; pclsObj[0]->Release(); } else break; } } return hRes; } /* * 結果セットの項目数を取得する * param : 無し * * return : size_t */ size_t WmiResult::items() { return properties.size(); } /* * 結果セットの行数を取得する * param : 無し * * return : size_t */ size_t WmiResult::size() { return results.size(); } /* * 結果セットのプロパティ一覧を取得する * param : 無し * * return : string_vector */ string_vector WmiResult::getProperties() { string_vector key_list; for (psIter item = properties.begin(); item != properties.end(); item++) { key_list.push_back(item->first); } return key_list; } /* * 結果セットのプロパティを取得する * param : 項目位置(size_t) * * return : String */ String WmiResult::getProperty(size_t pos) { string_vector key_list; for (psIter item = properties.begin(); item != properties.end(); item++) { if (item->second == pos) return item->first; } return _T(""); } /* * 結果セットを取得する * param : 無し * * return : result_set */ result_set WmiResult::getResult() { return results; } /* * 指定の行とプロパティで特定されるデータを取得する * param : プロパティ(String) * 行(size_t) * * return : VARIANT */ VARIANT *WmiResult::getValue(String prop, size_t row) { psIter ps = properties.find(prop); if (ps != properties.end()) { size_t col_pos = ps->second; rsIter rs = results.find(row); if (rs != results.end()) { rrIter rr = rs->second.find(col_pos); if (rr != rs->second.end()) { return &rr->second; } } } return NULL; } /* * 指定の行とプロパティで特定されるデータのタイプ取得する * param : プロパティ(String) * 行(size_t) * * return : VARTYPE */ VARTYPE WmiResult::getValueType(String prop, size_t row) { VARIANT *value = getValue(prop, row); return getType(value); } /* * 指定の行とプロパティで特定されるデータが配列(safaarray)かどうか確認する * param : プロパティ(String) * 行(size_t) * * return : bool */ bool WmiResult::isArray(String prop, size_t row) { VARIANT *value = getValue(prop, row); return isArray(value); } /* * 指定の行とプロパティで特定されるデータを整数値(long)で取得する * param : プロパティ(String) * 行(size_t) * 変換できないタイプの省略値(long) * * return : long */ long WmiResult::getLong(String prop, size_t row, long deflong) { VARIANT *value = getValue(prop, row); return getLong(value, deflong); } /* * 指定の行とプロパティで特定されるデータを整数値(long)リストで取得する * param : プロパティ(String) * 行(size_t) * 変換できないタイプの省略値(long) * * return : long_vector */ long_vector WmiResult::getLongArray(String prop, size_t row, long deflong) { VARIANT *value = getValue(prop, row); return getLongArray(value, deflong); } /* * 指定の行とプロパティで特定されるデータを浮動小数点値(double)で取得する * param : プロパティ(String) * 行(size_t) * 変換できないタイプの省略値(double) * * return : double */ double WmiResult::getDouble(String prop, size_t row, double defdouble) { VARIANT *value = getValue(prop, row); return getDouble(value, defdouble); } /* * 指定の行とプロパティで特定されるデータを浮動小数点値(double)リストで取得する * param : プロパティ(String) * 行(size_t) * 変換できないタイプの省略値(double) * * return : double_vector */ double_vector WmiResult::getDoubleArray(String prop, size_t row, double defdouble) { VARIANT *value = getValue(prop, row); return getDoubleArray(value, defdouble); } /* * 指定の行とプロパティで特定されるデータを論理値(bool)で取得する * param : プロパティ(String) * 行(size_t) * 変換できないタイプの省略値(bool) * * return : bool */ bool WmiResult::getBool(String prop, size_t row, bool defbool) { VARIANT *value = getValue(prop, row); return getBool(value, defbool); } /* * 指定の行とプロパティで特定されるデータを論理値(bool)リストで取得する * param : プロパティ(String) * 行(size_t) * 変換できないタイプの省略値(bool) * * return : bool_vector */ bool_vector WmiResult::getBoolArray(String prop, size_t row, bool defbool) { VARIANT *value = getValue(prop, row); return getBoolArray(value, defbool); } /* * 指定の行とプロパティで特定されるデータを文字列値で取得する * param : プロパティ(String) * 行(size_t) * * return : String */ String WmiResult::getString(String prop, size_t row) { VARIANT *value = getValue(prop, row); return getString(value); } /* * 指定の行とプロパティで特定されるデータを文字列値リストで取得する * param : プロパティ(String) * 行(size_t) * * return : string_vector */ string_vector WmiResult::getStringArray(String prop, size_t row) { VARIANT *value = getValue(prop, row); return getStringArray(value); } /* * 保持しているデータを印刷できる形式に変換する * param : 無し * * return : String */ String WmiResult::print() { basic_stringstream<_TCHAR> buf; string_vector key_list = getProperties(); for (size_t i = 0; i < rows; i++) { for (size_t j = 0; j < cols; j++) { String prop = key_list[j]; VARIANT *val = getValue(prop, i); if (isArray(val)) { string_vector list = getStringArray(val); buf << i << _T("-") << j << _T("=") << prop << _T(" : "); for (size_t k = 0; k < list.size(); k++) { if (k > 0) buf << _T(", "); buf << list.at(k); } buf << endl; } else { buf << i << _T("-") << j << _T("=") << prop << _T(" : ") << getString(val) << endl; } } } return buf.str(); } /* * VARIANTデータのタイプ取得する * param : VARIANTデータ(VARIANTポインター) * * return : VARTYPE */ VARTYPE WmiResult::getType(VARIANT *value) { if (value != NULL) { VARTYPE vt = value->vt; vt -= ((vt & VT_BYREF) == VT_BYREF) ? VT_BYREF : 0; vt -= ((vt & VT_ARRAY) == VT_ARRAY) ? VT_ARRAY : 0; return vt; } return VT_UNKNOWN; } /* * VARIANTデータが配列(safaarray)かどうか確認する * param : VARIANTデータ(VARIANTポインター) * * return : bool */ bool WmiResult::isArray(VARIANT *value) { if (value != NULL) { return ((value->vt & VT_ARRAY) == VT_ARRAY) ? true : false; } return false; } /* * VARIANTデータが参照値(VT_BYREF)かどうか確認する * param : VARIANTデータ(VARIANTポインター) * * return : bool */ bool WmiResult::isByRef(VARIANT *value) { if (value != NULL) { return ((value->vt & VT_BYREF) == VT_BYREF) ? true : false; } return false; } /* * VARIANTデータを整数値(long)に変換し取得する * param : データ(VARIANTポインター) * * return : long */ long WmiResult::getLong(VARIANT *value, long deflong) { long result = deflong; if (value != NULL) { if (isArray(value)) { long_vector list = getLongArray(value, deflong); if (!list.empty()) result = list.at(0); } else { VARIANT to_value; VariantInit(&to_value); VARTYPE vt = getType(value); /* * VARIANTデータのデータタイプを変換する * return : S_OK = 正常に変換できた * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221258.aspx */ if (VariantChangeType(&to_value, value, 0, VT_UI4) == S_OK) { result = to_value.lVal; } VariantClear(&to_value); } } return result; } /* * VARIANTデータ配列を整数値(long)リストに変換し取得する * param : データ(VARIANTポインター) * * return : long_vector */ long_vector WmiResult::getLongArray(VARIANT *value, long deflong) { long_vector list; if (value != NULL) { if (isArray(value)) { VARIANT array_var; VARTYPE vt = getType(value); long lb = 0, ub = 0; SAFEARRAY *array_val = ((isByRef(value)) ? *value->pparray : value->parray); SafeArrayGetLBound(array_val, 1, &lb); SafeArrayGetUBound(array_val, 1, &ub); for (long i = 0; i <= (ub - lb); i++) { VariantInit(&array_var); array_var.vt = vt; SafeArrayGetElement(array_val, &i, (void*)&array_var.punkVal); long result = getLong(&array_var, deflong); list.push_back(result); } } else { long result = getLong(value, deflong); list.push_back(result); } } return list; } /* * VARIANTデータを浮動小数点値(double)に変換し取得する * param : データ(VARIANTポインター) * * return : double */ double WmiResult::getDouble(VARIANT *value, double defdouble) { double result = defdouble; if (value != NULL) { if (isArray(value)) { double_vector list = getDoubleArray(value, defdouble); if (!list.empty()) result = list.at(0); } else { VARIANT to_value; VariantInit(&to_value); VARTYPE vt = getType(value); VariantChangeType(&to_value, value, 0, VT_R8); result = to_value.dblVal; VariantClear(&to_value); } } return result; } /* * VARIANTデータ配列を浮動小数点値(double)リストに変換し取得する * param : データ(VARIANTポインター) * * return : double_vector */ double_vector WmiResult::getDoubleArray(VARIANT *value, double defdouble) { double_vector list; if (value != NULL) { if (isArray(value)) { VARIANT array_var; VARTYPE vt = getType(value); long lb = 0, ub = 0; SAFEARRAY *array_val = ((isByRef(value)) ? *value->pparray : value->parray); SafeArrayGetLBound(array_val, 1, &lb); SafeArrayGetUBound(array_val, 1, &ub); for (long i = 0; i <= (ub - lb); i++) { VariantInit(&array_var); array_var.vt = vt; SafeArrayGetElement(array_val, &i, (void*)&array_var.punkVal); double result = getDouble(&array_var, defdouble); list.push_back(result); } } else { double result = getDouble(value, defdouble); list.push_back(result); } } return list; } /* * VARIANTデータを論理値(bool)に変換し取得する * param : データ(VARIANTポインター) * * return : bool */ bool WmiResult::getBool(VARIANT *value, bool defbool) { bool result = defbool; if (value != NULL) { if (isArray(value)) { bool_vector list = getBoolArray(value, defbool); if (!list.empty()) result = list.at(0); } else { VARIANT to_value; VariantInit(&to_value); VARTYPE vt = getType(value); VariantChangeType(&to_value, value, 0, VT_BOOL); result = (to_value.boolVal != 0) ? true : false; VariantClear(&to_value); } } return result; } /* * VARIANTデータ配列を論理値(bool)リストに変換し取得する * param : データ(VARIANTポインター) * * return : bool_vector */ bool_vector WmiResult::getBoolArray(VARIANT *value, bool defbool) { bool_vector list; if (value != NULL) { if (isArray(value)) { VARIANT array_var; VARTYPE vt = getType(value); long lb = 0, ub = 0; SAFEARRAY *array_val = ((isByRef(value)) ? *value->pparray : value->parray); SafeArrayGetLBound(array_val, 1, &lb); SafeArrayGetUBound(array_val, 1, &ub); for (long i = 0; i <= (ub - lb); i++) { VariantInit(&array_var); array_var.vt = vt; SafeArrayGetElement(array_val, &i, (void*)&array_var.punkVal); bool result = getBool(&array_var, defbool); list.push_back(result); } } else { bool result = getBool(value, defbool); list.push_back(result); } } return list; } /* * VARIANTデータを文字列値に変換し取得する * param : データ(VARIANTポインター) * * return : String */ String WmiResult::getString(VARIANT *value) { String result; if (value != NULL) { if (isArray(value)) { string_vector list = getStringArray(value); if (!list.empty()) result = list.at(0); } else { VARIANT to_value; VariantInit(&to_value); VARTYPE vt = getType(value); switch (vt) { case VT_BOOL: // VARIANT_BOOL /* * VT_BOOL型のデータをVT_BST型のデータに変換 * return : S_OK = 正常に変換できた(ここでは結果はチェックしない) * その他 = エラー * 参照:http://msdn.microsoft.com/en-us/library/ms221338.aspx */ VarBstrFromBool(((isByRef(value)) ? *value->pboolVal : value->boolVal), 0, LOCALE_NOUSEROVERRIDE, &to_value.bstrVal); break; case VT_BSTR: // VT_BSTR VariantCopy(&to_value, value);; break; default: VariantChangeType(&to_value, value, 0, VT_BSTR); } result = String(to_value.bstrVal); VariantClear(&to_value); } } return result; } /* * VARIANTデータ配列を文字列値リストに変換し取得する * param : データ(VARIANTポインター) * * return : string_vector */ string_vector WmiResult::getStringArray(VARIANT *value) { string_vector list; if (value != NULL) { if (isArray(value)) { VARIANT array_var; VARTYPE vt = getType(value); long lb = 0, ub = 0; SAFEARRAY *array_val = ((isByRef(value)) ? *value->pparray : value->parray); SafeArrayGetLBound(array_val, 1, &lb); SafeArrayGetUBound(array_val, 1, &ub); for (long i = 0; i <= (ub - lb); i++) { VariantInit(&array_var); array_var.vt = vt; SafeArrayGetElement(array_val, &i, (void*)&array_var.punkVal); String result = getString(&array_var); list.push_back(result); } } else { String result = getString(value); list.push_back(result); } } return list; }
にしてみました。
で、呼出すプログラムのコードは、
WmiCall wmi; size_t key_wait(String question = _T("")) { if (question.empty()) COUT << _T("\nPress enter key to continue :"); else COUT << question; String value; getline(CIN, value, _T('\n')); return value.length(); } void Win32_BootConfiguration() { WmiResult results = wmi.access(_T("SELECT * FROM Win32_BIOS")); if (results.items() == 0) { String msg = wmi.getErrorMessage(); return; } COUT << results.print(); } int _tmain(int argc, _TCHAR* argv[]) { if (wmi.init()) { Win32_BootConfiguration(); wmi.term(); } key_wait(); return 0; }
って感じで動作結果は・・・、色んな情報が入っていたので割愛しました。