You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过C++读取WQL查询获取的WMI日志文件所有字段?

Fixing Invalid Field Reads in WMI Win32_NTLogEvent Queries

Hey there! Let's figure out why only a couple of fields are returning correct values in your WMI query results, and how to fix the rest. The core issue here is that you're not accounting for the different data types returned by WMI properties—each field uses a specific VARIANT type, and accessing the wrong VARIANT member leads to garbage values or memory addresses instead of actual data.

Key Problems in Your Current Code

  1. No type checking for VARIANTs: You're directly accessing members like plVal or bstrVal without verifying what type of data the VARIANT holds. For example, Id is an unsigned integer, not a pointer or string.
  2. Missing error checks: You don't verify if pclsobj->Get() succeeds before reading the VARIANT. If the call fails, you're reading uninitialized memory.
  3. Incorrect handling of special types: Fields like TimeCreated are datetime values, which can't be read directly with standard string/int members.

Step-by-Step Fixes

1. Always Check HRESULT for Get() Calls

Before accessing any VARIANT data, confirm that the Get() method succeeded. This avoids reading invalid memory if the property doesn't exist or can't be retrieved.

2. Match VARIANT Type to WMI Property

Each Win32_NTLogEvent property has a defined data type. Here's how to handle the fields you're struggling with:

Example: Correctly Read Id

Id is a uint32 type, which maps to VT_UI4 in VARIANT. Access the ulVal member instead of plVal:

VARIANT vtProp;
HRESULT hr = pclsobj->Get(L"Id", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
    if (vtProp.vt == VT_UI4) {
        wcout << L"Id : " << vtProp.ulVal << endl;
    } else {
        wcout << L"Id: Unexpected data type (VT=" << vtProp.vt << L")" << endl;
    }
    VariantClear(&vtProp);
} else {
    wcout << L"Failed to retrieve Id (HRESULT: " << hex << hr << L")" << endl;
}

Example: Correctly Read ProviderName

ProviderName is a string (VT_BSTR), but ensure you only access bstrVal if the type matches:

hr = pclsobj->Get(L"ProviderName", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
    if (vtProp.vt == VT_BSTR) {
        wcout << L"ProviderName : " << vtProp.bstrVal << endl;
    } else {
        wcout << L"ProviderName: Unexpected data type (VT=" << vtProp.vt << L")" << endl;
    }
    VariantClear(&vtProp);
} else {
    wcout << L"Failed to retrieve ProviderName (HRESULT: " << hex << hr << L")" << endl;
}

Example: Correctly Read Level

Like Id, Level is a uint32 (VT_UI4):

hr = pclsobj->Get(L"Level", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
    if (vtProp.vt == VT_UI4) {
        wcout << L"Level : " << vtProp.ulVal << endl;
    } else {
        wcout << L"Level: Unexpected data type (VT=" << vtProp.vt << L")" << endl;
    }
    VariantClear(&vtProp);
} else {
    wcout << L"Failed to retrieve Level (HRESULT: " << hex << hr << L")" << endl;
}

Example: Handle TimeCreated (Datetime Type)

TimeCreated is a datetime type (VT_DATE). Convert it to a readable string using VariantTimeToSystemTime:

hr = pclsobj->Get(L"TimeCreated", 0, &vtProp, 0, 0);
if (SUCCEEDED(hr)) {
    if (vtProp.vt == VT_DATE) {
        SYSTEMTIME st;
        if (VariantTimeToSystemTime(vtProp.date, &st)) {
            wchar_t timeBuffer[100];
            swprintf_s(timeBuffer, L"%02d-%02d-%04d %02d:%02d:%02d",
                st.wDay, st.wMonth, st.wYear,
                st.wHour, st.wMinute, st.wSecond);
            wcout << L"TimeCreated : " << timeBuffer << endl;
        } else {
            wcout << L"Failed to convert datetime value" << endl;
        }
    } else {
        wcout << L"TimeCreated: Unexpected data type (VT=" << vtProp.vt << L")" << endl;
    }
    VariantClear(&vtProp);
} else {
    wcout << L"Failed to retrieve TimeCreated (HRESULT: " << hex << hr << L")" << endl;
}

3. Handle Null/Empty Values

Some fields (like Version in your CSV) may be empty. In these cases, the VARIANT's vt will be VT_NULL. Add a check to handle this gracefully:

if (vtProp.vt == VT_NULL) {
    wcout << L"[Field Name]: (empty)" << endl;
}

Full Modified Loop Example

Here's how your data retrieval loop should look with these fixes:

IWbemClassObject *pclsobj = NULL ; 
ULONG uReturn = 0 ; 
while (pEnumerator) {
    HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsobj, &uReturn);
    if( 0 == uReturn ) {
        cout << "loop broke" << endl ; 
        break; 
    }

    // Message (string)
    VARIANT vtProp;
    hr = pclsobj->Get(L"Message", 0, &vtProp, 0, 0);
    if (SUCCEEDED(hr)) {
        if (vtProp.vt == VT_BSTR) {
            wcout << L"Message : " << vtProp.bstrVal << endl ; 
        } else if (vtProp.vt == VT_NULL) {
            wcout << L"Message : (empty)" << endl;
        } else {
            wcout << L"Message: Unexpected type" << endl;
        }
        VariantClear(&vtProp);
    }

    // ComputerName (string)
    hr = pclsobj->Get(L"ComputerName", 0, &vtProp, 0, 0);
    if (SUCCEEDED(hr)) {
        if (vtProp.vt == VT_BSTR) {
            wcout << L"ComputerName : " << vtProp.bstrVal << endl;
        }
        VariantClear(&vtProp);
    }

    // Id (uint32)
    hr = pclsobj->Get(L"Id", 0, &vtProp, 0, 0);
    if (SUCCEEDED(hr)) {
        if (vtProp.vt == VT_UI4) {
            wcout << L"Id : " << vtProp.ulVal << endl ; 
        } else if (vtProp.vt == VT_NULL) {
            wcout << L"Id : (empty)" << endl;
        }
        VariantClear(&vtProp);
    }

    // Add other fields using the same pattern...

    pclsobj->Release(); 
}

Additional Notes

  • For complex fields like Properties or KeywordsDisplayNames (arrays/collections), you'll need to iterate over the VARIANT's array data (using parray member and SafeArray functions).
  • Always call VariantClear() after using a VARIANT to avoid memory leaks.

内容的提问来源于stack exchange,提问作者D vignesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:50:11