从 C++ 中 WMI 中的 OUT 参数获取值

Posted

技术标签:

【中文标题】从 C++ 中 WMI 中的 OUT 参数获取值【英文标题】:Getting value from an OUT parameter in WMI in C++ 【发布时间】:2014-02-10 13:11:23 【问题描述】:

我正在尝试使用 WMI 读取注册表值。这是我现在拥有的:

    BSTR methodName = SysAllocString(L"GetStringValue");
    BSTR className = SysAllocString(L"StdRegProv");
    IWbemClassObject* pInParamsDefinition = nullptr;

    std::wstring errStr = L"ERROR";

    HRESULT hRes = p_regWbemClassObj->GetMethod(methodName, 0, &pInParamsDefinition, NULL);

    IWbemClassObject* pClassInstance = NULL;
    hRes = pInParamsDefinition->SpawnInstance(0, &pClassInstance);

    // Create the values for the in parameters
    VARIANT sSubKeyName;
    sSubKeyName.vt = VT_BSTR;
    sSubKeyName.bstrVal = BSTR(path.c_str());
    VARIANT sValueName;
    sValueName.vt = VT_BSTR;
    sValueName.bstrVal = BSTR(key.c_str());


    // Store the value for the in parameters
    hRes = pClassInstance->Put(L"sSubKeyName", 0,
        &sSubKeyName, 0);
    hRes = pClassInstance->Put(L"sValueName", 0,
        &sSubKeyName, 0);

    // Execute Method
    IWbemClassObject* pOutParams = NULL;
    hRes = p_defWbemServices->ExecMethod(className, methodName, 0,
        NULL, pClassInstance, &pOutParams, NULL);

    if (FAILED(hRes))
    
        VariantClear(&sSubKeyName);
        VariantClear(&sValueName);
        SysFreeString(className);
        SysFreeString(methodName);
        pInParamsDefinition->Release();
        pClassInstance->Release();
        pOutParams->Release();
        return errStr;
    


    VARIANT varReturnValue;
    hRes = pOutParams->Get(BSTR(L"sValue"), 0, &varReturnValue, NULL, NULL);

    std::wstring result = varReturnValue.bstrVal;

由于某种原因,我从未得到正确的 varReturnValue。 这是函数:http://msdn.microsoft.com/en-us/library/aa390788(v=vs.85).aspx

【问题讨论】:

【参考方案1】:

已经有一段时间了,但是...您是否首先在 Variant 上调用了 VariantInit。 IIRC 在调用 COM 方法时需要初始化。

【讨论】:

【参考方案2】:

这是一个可以回答您问题的示例。在示例中,我找出了当前正在打印的文档的名称。

using std::cout;
using std::cin;
using std::endl;

HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hRes))

    cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
    return 1;


if ((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))

    cout << "Unable to initialize security: 0x" << std::hex << hRes << endl;
    return 1;


IWbemLocator* pLocator = NULL;
if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))

    cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
    return 1;


IWbemServices* pService = NULL;
if (FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))

    pLocator->Release();
    cout << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
    return 1;


IEnumWbemClassObject* pEnumerator = NULL;
if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT Documents FROM Win32_PrintJob", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))

    pLocator->Release();
    pService->Release();
    cout << "Unable to retrive desktop monitors: " << std::hex << hRes << endl;
    return 1;


IWbemClassObject* clsObj = NULL;
int numElems;
while ((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)

    if (FAILED(hRes))
        break;

    VARIANT vRet;
    VariantInit(&vRet);
    if (SUCCEEDED(clsObj->Get(L"Description", 0, &vRet, NULL, NULL)) && vRet.vt == VT_BSTR)
    
        std::wcout << L"Description: " << vRet.bstrVal << endl;
        VariantClear(&vRet);
    

    clsObj->Release();


pEnumerator->Release();
pService->Release();
pLocator->Release();
return 0;

【讨论】:

【参考方案3】:

您在“sSubKeyName”和“sValueName”中输入了相同的值 - &sSubKeyName。

// Store the value for the in parameters
    hRes = pClassInstance->Put(L"sSubKeyName", 0,
        &sSubKeyName, 0); // <-- sSubKeyName
    hRes = pClassInstance->Put(L"sValueName", 0,
        &sSubKeyName, 0); // <-- sSubKeyName

我认为你的本意是:

// Store the value for the in parameters
        hRes = pClassInstance->Put(L"sSubKeyName", 0,
            &sSubKeyName, 0); // <-- sSubKeyName
        hRes = pClassInstance->Put(L"sValueName", 0,
            &sValueName, 0); // <-- sValueName

【讨论】:

以上是关于从 C++ 中 WMI 中的 OUT 参数获取值的主要内容,如果未能解决你的问题,请参考以下文章

检查多个列在表值参数中具有多个值中的任何一个

无法从 JDBC 获取 OUT 参数中的二维关联数组

如何从 QMultiMap 中的值中获取键?

使用 WMI 拉回远程 netstat 数据

我无法从 laravel 中的输入值中获取请求值

C++调用WMI类查询获取操作系统名