Windows Management Instrumentation (2)

WmiCallの処理結果をAPIネイティブの結果(IEnumWbemClassObject)ではなく、WmiResultクラスに格納するように修正しました。

wmi.hの定義で

    IEnumWbemClassObject    *access(String select_stmt);

    WmiResult               access(String select_stmt, bool with_valus = true);

に変更。

wmi.cppのaccessメソッドを

/*
 *  WQLを実行し結果セットを取得する
 *  param   : 実行するWQL文(String)
 *
 *  return  : IEnumWbemClassObjectポインター
 */
WmiResult WmiCall::access(String select_stmt, bool with_valus) {
    WmiResult result;
    if (pSvc != NULL) {
        IEnumWbemClassObject *pObjects = 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_RETURN_IMMEDIATELY | WBEM_FLAG_ENSURE_LOCATABLE,
                               NULL,
                               &pObjects);
        if (hRes != WBEM_S_NO_ERROR) {
            pObjects = NULL;
            errPos = 5;
        }
        if ((hRes = result.loadProperties(pObjects)) == WBEM_S_NO_ERROR) {
            if (with_valus) {
                if ((hRes = result.loadValues(pObjects)) != WBEM_S_NO_ERROR) {
                    errPos = 7;
                }
            }
        }
        else {
            errPos = 7;
        }
    }
    else {
        errPos = 6;
        hRes = WBEM_E_FAILED;
    }
    return result;
}

に変更しました。

そしてwmi.hファイルに新たなWmiResultクラスを定義

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();

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
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++) {
            VariantInit(&to_value);
            VariantCopy(&to_value, (VARIANT*)&rr->second);
            to_row[rr->first] = to_value;
        }
        results[rs->first] = to_row;
    }
}

//  Destructor
WmiResult::~WmiResult() {
}

/*
 *  WMI呼び出しで戻ってきた結果セットからプロパティを保存する
 *  param   : 結果セット(IEnumWbemClassObjectポインター)
 *
 *  return  : HRESULT
 */
HRESULT WmiResult::loadProperties(IEnumWbemClassObject *pObjects) {
    HRESULT hRes;
    if (pObjects == NULL) {
        return WBEM_E_FAILED;
    }

    if ((hRes = pObjects->Reset()) == WBEM_S_NO_ERROR) {
        wchar_t **names = NULL;
        long lb = 0, ub = 0;
        ULONG uReturn = 0;
        IWbemClassObject *pclsObj[1];
        if ((hRes = pObjects->Next(WBEM_INFINITE, 1, pclsObj, &uReturn)) == WBEM_S_NO_ERROR) {
            SAFEARRAY *pstrNames = NULL;
            if ((hRes = pclsObj[0]->GetNames(NULL, WBEM_FLAG_ALWAYS, NULL, &pstrNames)) == WBEM_S_NO_ERROR) {
                SafeArrayGetLBound(pstrNames, 1, &lb);
                SafeArrayGetUBound(pstrNames, 1, &ub);
                SafeArrayAccessData(pstrNames, (void **)&names);
                for (int i = lb; i <= ub; i++) {
                    String name = String((_TCHAR *)bstr_t(names[i]));
                    properties[name] = cols++;
                }
                SafeArrayUnaccessData(pstrNames);
                SafeArrayDestroy(pstrNames);
            }
        }
    }
    return hRes;
}

/*
 *  WMI呼び出しで戻ってきた結果セットからデータを保存する
 *  param   : 結果セット(IEnumWbemClassObjectポインター)
 *
 *  return  : HRESULT
 */
HRESULT WmiResult::loadValues(IEnumWbemClassObject *pObjects) {
    HRESULT hRes;
    if (pObjects == NULL) {
        return WBEM_E_FAILED;
    }

    if ((hRes = pObjects->Reset()) == WBEM_S_NO_ERROR) {
        VARIANT vtProp, value;
        VariantInit(&vtProp);
        ULONG uReturn = 0;
        IWbemClassObject *pclsObj[1];
        while (pObjects != NULL) {
            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());
                    hRes = pclsObj[0]->Get(key, 0, &vtProp, 0, 0);
                    VariantInit(&value);
                    if (vtProp.vt != 1) {
                        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   : 項目位置
 *
 *  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;
}

もう少しクラスらしくは明日以降頑張ろうかな・・・。