如何使用c++在WMI中获取CPU使用率

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

本文关键字:获取 CPU 使用率 WMI 何使用 c++      更新时间:2023-10-16

我读过很多这样的问题,但是在使用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);
  • Win32_PerfRawData_PerfOS_Processor中得到一些数据,然后使用公式。然而,当我尝试这种方法时,我总是得到关于PercentProcessorTimeTimeStamp_Sys100NS的相同值,也就是说N1=N2D1=D2。我认为我的代码中一定有一些错误
  • 公式- (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中的步骤1-5进行。我需要在两个不同的WMI连接中获取它们的值吗?在当前情况下,我只是在两个不同的时间查询类。这是为什么我总是得到相同的值的原因吗?

    我的建议是使用'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使用情况。