spartawhy117
spartawhy117

Reputation: 561

How to get CPU usage in WMI using C++?

I have read most questions like this .But there are still some problems when try get the value of cpu usage in WMI using c++.

I have tried two ways to solve this problem:

  1. query the value of PercentProcessorTime in Win32_PerfFormattedData_PerfOS_Processor.But the value is much bigger than I want . It can reach 10802692. some pieces of my code:

hres = m_pWbemSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor where Name='_Total' "),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&m_pEnumClsObj
);

hres = m_pWbemClsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);
        wcout << "CPU Usage : " << vtProp.ullVal << endl;
        VariantClear(&vtProp);
  1. get the some data form Win32_PerfRawData_PerfOS_Processor,then using the formula.However,when I try this method , I always get same value about PercentProcessorTime and TimeStamp_Sys100NS.That is to say N1=N2 and D1=D2.I think there must be some wrong in my code

Formula - (1- ((N2 - N1) / (D2 - D1))) x 100

unsigned __int64 N1;
unsigned __int64 D1;
unsigned __int64 N2;
unsigned __int64 D2;
bool result = false;


if (getCPUData(&N1, &D1))
{
    Sleep(1000);

    if (getCPUData(&N2, &D2))
    {
        result = true;
    }
}

//(1 - ((N2 - N1) / (D2 - D1))) * 100;

bool WMI_Util::getCPUData(unsigned __int64 *N, unsigned __int64 *D)
{
HRESULT hres;
ULONG uReturn = 0;
VARIANT vtProp;
m_pEnumClsObj = NULL;
bool result = false;


hres = m_pWbemSvc->ExecQuery(
    bstr_t("WQL"),
    bstr_t("SELECT * FROM Win32_PerfRawData_PerfOS_Processor where Name='_Total' "),
    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    NULL,
    &m_pEnumClsObj
    );

if (FAILED(hres))
{
    wcout << L"Query for operating system name failed."
        << L" Error code = 0x"
        << hex << hres << endl;
    m_pWbemSvc->Release();
    m_pWbemLoc->Release();
    CoUninitialize();
}
else{

    m_pWbemClsObj = NULL;

    while (m_pEnumClsObj)
    {
        hres = m_pEnumClsObj->Next(WBEM_INFINITE, 1, &m_pWbemClsObj, &uReturn);

        if (0 == uReturn)
            break;

        hres = m_pWbemClsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);
        *N = vtProp.ullVal;
        VariantClear(&vtProp);

        hres = m_pWbemClsObj->Get(L"TimeStamp_Sys100NS", 0, &vtProp, 0, 0);
        *D = vtProp.ullVal;
        VariantClear(&vtProp);

        m_pWbemClsObj->Release();

  }
    result = true;
}
return result;
ReleaseWMI();
}

As for initialization of WMI, I followed the step1-5 in MSDN. Do I need to get the value of them in two different WMI connection? In current situation , I just query the class in two different time .Is this reason why I always get the same value?

Upvotes: 0

Views: 2464

Answers (1)

Meir G.
Meir G.

Reputation: 46

My advice is to use 'vtProp.bstrVal' instead of 'vtProp.ullVal'. I implemented very similar function and as you said got constant values in numeric fields but I got correct value in string field.

Here is my method (without debug printings):

HRESULT WMI_sdk_services::GetCpuUsage(int &cpuUsage)
{
  bool shouldUninitializeComAfterWmiRequest; //out parameter

  HRESULT hres = PrepareEnumWbemClassObject(true, shouldUninitializeComAfterWmiRequest, L"SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor where Name='_Total'");

  IWbemClassObject *pclsObj = NULL;
  ULONG uReturn = 0;

  if(SUCCEEDED(hres)){

    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

        VARIANT vtProp;

        // Get the value of the 'PercentProcessorTime' property
        hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);

        if (WBEM_S_NO_ERROR != hr) {

            if(pclsObj){
                VariantClear(&vtProp);
                pclsObj->Release(); pclsObj = NULL;
            }
            break;
        }
        cpuUsage = std::stoi(vtProp.bstrVal);

        VariantClear(&vtProp);

        pclsObj->Release(); pclsObj = NULL;           
    }
  }

  return hres;    
}

Another remark: You get here total CPU usage not your process CPU usage.

Upvotes: 0

Related Questions