Search code examples
c++winapicpu-usagepdh

C++ - Find current CPU usage in Hertz (Windows)


Current Situation:
I'm looking to try and measure the current CPU utilisation of my system in Hertz.

I've had a look at this answer which addresses my question, however I cannot seem to make the code work.

This is my current code in main.cpp (from the answer):

#include <Pdh.h>
#include <PdhMsg.h>
#include <Windows.h>

static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal;

void init()
{
    PDH_STATUS a = PdhOpenQuery(NULL, NULL, &cpuQuery);
    PDH_STATUS i = PdhAddCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
    PdhCollectQueryData(cpuQuery);
}

double getCurrentValue()
{
    init();
    PDH_FMT_COUNTERVALUE counterVal;

    PdhCollectQueryData(cpuQuery);
    PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
    return counterVal.doubleValue;
}

int main()
{
    double CPUUsage = getCurrentValue();
}

The Problem:
The value returned from getCurrectValue() is zero.

Related Observations:
I have observed, that the values in a and i of type PDH_STATUS are both zero? I speculate that this could be related to my lack of a value in CPUUsage, although I'm not sure why the function wouldn't be returning properly into these values.

Additional information:
I haven't used PDH before.


Solution

  • It's a PdhAddCoutner() is language dependent. You should use PdhAddEnglishCounter() instead.

    EDIT: And you should have a minimal delay (500ms) between the query ran in the init() and the query in getvalue().

    Additional explanations:

    Running your code on my windows 8.1 system, it turned out that in init(), the status i returned was PDH_CSTATUS_NO_OBJECT, which means that it didn't find the object "Processor(_Total)".

    I first thought there was a typo, and verified the name of the object and the counter on Technet.

    By curiosity, I ran the original windows command perfmon.exe and noticed that all the objects and counter were translated in my native language. Running your code using the native language name of the counter gave me the correct result.

    About the timing constraint

    Once the language issue addressed, debugging step by step I got meaningful values of my CPU usage. But once I removed the breakpoints, I got either 0 or 100.

    So I dug a little further in this issue to find out on microsoft support that % rates require some minimal delays between two consecutive queries. Once I added a Sleep(1000) at exit of init, I got again meaningful CPU usage values.