Reputation: 319
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.
Upvotes: 2
Views: 2497
Reputation: 73376
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.
Upvotes: 5
Reputation: 2705
/* Needed windows definitions by following header */
#include <windef.h>
/* Windows performance data helper */
#include <Pdh.h>
/* Storage of PDH query and associated cpu counter */
struct cpu_counter{
PDH_HQUERY query;
PDH_HCOUNTER counter;
};
/* Initialize query & counter */
int cpu_counter_init(struct cpu_counter* pcc)
{
if(PdhOpenQueryA(NULL, 0, &pcc->query) != ERROR_SUCCESS)
return -1;
if(PdhAddEnglishCounterA(pcc->query, "\\Processor(_Total)\\% Processor Time", 0, &pcc->counter) != ERROR_SUCCESS || PdhCollectQueryData(pcc->query) != ERROR_SUCCESS)
{
PdhCloseQuery(pcc->query);
return -2;
}
return 0;
}
/* Fetch data from query and evaluate current counter value */
int cpu_counter_get(struct cpu_counter* pcc)
{
PDH_FMT_COUNTERVALUE counter_val;
if(PdhCollectQueryData(pcc->query) != ERROR_SUCCESS || PdhGetFormattedCounterValue(pcc->counter, PDH_FMT_LONG, NULL, &counter_val) != ERROR_SUCCESS)
return -1;
return counter_val.longValue;
}
/* Close all counters of query and query itself at the end */
void cpu_counter_close(struct cpu_counter* pcc)
{
if(pcc->query != NULL)
{
PdhCloseQuery(pcc->query);
pcc->query = NULL;
}
}
No ugly statics, status checks, use of instances instead of global, minimal include, save even without unicode definition, solution of Christophe (plz rather upvote him than me) built-in.
Upvotes: 0