如何使用 C++ 在 WMI 中获取 CPU 用法?

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

我已经阅读了大多数这样的问题。但是当尝试使用 C++ 在 WMI 中获取 cpu 用法的值时仍然存在一些问题。

我尝试了两种方法来解决这个问题:

  1. 查询Win32_PerfFormattedData_PerfOS_ProcessorPercentProcessorTime的值。但是这个值比我想要的大很多。可以达到10802692。我的部分代码:

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. 获取一些数据形式 Win32_PerfRawData_PerfOS_Processor,然后使用 formula。但是,当我尝试这种方法时,我总是得到关于 PercentProcessorTimeTimeStamp_Sys100NS 相同的值.也就是说N1=N2D1=D2.我想我的代码肯定有问题

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

关于WMI的初始化,我按照MSDN中的step1-5进行了。我是否需要在两个不同的 WMI 连接中获取它们的值?在目前的情况下,我只是在两个不同的时间查询class。这就是为什么我总是得到相同值的原因吗?

我的建议是使用 'vtProp.bstrVal' 而不是 'vtProp.ullVal'。 我实现了非常相似的功能,正如你所说,在数字字段中得到了常量值,但我在字符串字段中得到了正确的值。

这是我的方法(没有调试打印):

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;    
}

另一句话:你在这里得到的是总 CPU 使用量,而不是你的过程 CPU 使用量。