C++ - найти текущее использование процессора в герцах (Windows)

Текущая ситуация:
Я пытаюсь измерить текущую загрузку процессора моей системы в герцах.

Я посмотрел на этот ответ, который отвечает на мой вопрос, однако я не могу заставить код работать.

Это мой текущий код в main.cpp (из ответа):

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

Эта проблема:
Значение, возвращаемое из getCurrectValue() это ноль.

Связанные наблюдения:
Я заметил, что значения в a а также i типа PDH_STATUS оба равны нулю? Я предполагаю, что это может быть связано с моим отсутствием значения в CPUUsage, хотя я не уверен, почему функция не будет возвращаться должным образом в эти значения.

Дополнительная информация:
Я не использовал PDH раньше.

2 ответа

Решение

Это PdhAddCoutner() зависит от языка. Вы должны использовать PdhAddEnglishCounter() вместо.

РЕДАКТИРОВАТЬ: И вы должны иметь минимальную задержку (500 мс) между запросом, запущенным в init() и запрос в getvalue(),

Дополнительные объяснения:

Запустив свой код в моей системе Windows 8.1, оказалось, что в init(), статус i вернулся был PDH_CSTATUS_NO_OBJECT, что означает, что он не нашел объект "Процессор (_Total)".

Сначала я подумал, что произошла опечатка, и проверил название объекта и счетчик на Technet.

Из любопытства я запустил оригинальную команду windows perfmon.exe и заметил, что все объекты и счетчик были переведены на мой родной язык. Запуск вашего кода с использованием названия счетчика на родном языке дал мне правильный результат.

О временном ограничении

Как только проблема с языком решена, пошагово отлаживая, я получил значимые значения использования моего процессора. Но как только я убрал контрольные точки, я получил 0 или 100.

Поэтому я немного углубился в этом вопросе, чтобы выяснить в службе поддержки Microsoft, что процентные ставки требуют минимальных задержек между двумя последовательными запросами. Однажды я добавил Sleep(1000) при выходе из init я снова получил значимые значения загрузки процессора.

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

Никакой уродливой статики, проверки статуса, использования экземпляров вместо глобальных, минимального включения, сохранения даже без определения юникода, встроенного решения Кристофа (пожалуйста, поддержите его, а не меня).

Другие вопросы по тегам