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

Для получения значений счетчиков использовалась библиотека PDH (Performance
Data Helper
), основу которой составляет pdh.dll —  через API функции,
содержащиеся в ней, мы сможем получить доступ к данным. В данной статье
рассматривается пример получения значения загруженности жесткого диска. В
комплекте поставки операционной системы Windows уже имеется программа для
просмотра и графического отображения значений счетчиков, perfmon.msc.

Perfmon

Для создания программы использовалась среда разработки Microsoft Visual C++
6.0
, тип проекта Win32 Console Application. Для получения индексов имен объектов
и имен счетчиков можно воспользоваться программой PCViewer (автор программы
Сергей Холодилов), скачать которую можно здесь:

http://www.rsdn.ru/article/baseserv/PerfCounters/code_1.zip
.

#include <iostream.h>
#include <windows.h>

Первое что необходимо сделать, это добавить в проект необходимые для работы
библиотеки заголовочные файлы:

#include <pdh.h>
#include <PDHMsg.h>

Подключаем lib файл к проекту:

#pragma comment(lib, "pdh.lib")

int main()
{

Создаем и инициализируем необходимые перемененные:

PDH_HQUERY hQuery;
CHAR szObjectName[256],szCounterName[256],szPath[256];
PDH_STATUS pdhStatus;
PDH_HCOUNTER * phCounter = (HCOUNTER*)GlobalAlloc(GPTR,sizeof(HCOUNTER));

Вызываем функцию PdhOpenQuery, тем самым создать запрос на использование
счетчиков производительности:

if(PdhOpenQuery(0,0,&hQuery) == ERROR_SUCCESS)
{
DWORD dwSize = sizeof(szObjectName);

Для формирования пути к счетчику производительности вызываем функцию
PdhLookupPerfNameByIndex, которая при вызове с определенным индексом (в данном
примере 234) возвращает имя или объект счетчика. Сначала нужно получить имя
объекта и сохранить его, после уже вторым вызовом получаем имя счетчика:

pdhStatus = PdhLookupPerfNameByIndex(NULL,234,szObjectName,&dwSize);//-1
if(pdhStatus == ERROR_SUCCESS)
{

cout<<"PdhLookupPerfNameByIndex(1) -ok- "<<szObjectName<<endl;
dwSize = sizeof(szCounterName);

Получаем имя счетчика производительности:

pdhStatus = PdhLookupPerfNameByIndex(NULL,200,szCounterName,&dwSize);//-2

if(pdhStatus == ERROR_SUCCESS)
{
cout<<"PdhLookupPerfNameByIndex(2) -ok- "<<szCounterName<<endl;

Далее заполняется структура PDH_COUNTER_PATH_ELEMENTS, где элементами
структуры являются имя объекта (szObjectName), имя счетчика (szCounterName), имя
машины (szMachineName) которое получаем при помощи вызова API функции
GetComputerName.

PDH_COUNTER_PATH_ELEMENTS pdh_elm;memset(&pdh_elm,0,sizeof(pdh_elm));

TCHAR szCompName[256];DWORD dwSize = sizeof(szCompName);
GetComputerName(szCompName,&dwSize); cout<<szCompName<<endl;
pdh_elm.szMachineName = szCompName;
pdh_elm.szObjectName = szObjectName;
pdh_elm.szInstanceName = "_Total";
pdh_elm.szParentInstance = NULL;
pdh_elm.dwInstanceIndex = 0;
pdh_elm.szCounterName = szCounterName;

dwSize = sizeof(szPath);

Следующим шагом формируем полный путь к счетчику, при помощи функции
PdhMakeCounterPath, одним из возвращаемых параметров которой будет полный путь к
счетчику в формате:
\\Computer\PerfObject(ParentInstance/ObjectInstance#InstanceIndex)\Counter.

pdhStatus = PdhMakeCounterPath(&pdh_elm,szPath,&dwSize,0);

if(pdhStatus == ERROR_SUCCESS)
{
cout<<"PdhMakeCounterPath -ok- "<<szPath<<endl;

При помощи функции PdhAddCounter добавляем счетчик к нашему запросу:

pdhStatus = PdhAddCounter(hQuery,szPath,0,phCounter);
if(pdhStatus == ERROR_SUCCESS)
{

cout<<"PdhAddCounter -ok-"<<endl;

В цикле выводим значения счетчика:

for(int i=0;i<10;i++)
{

После функцией PdhCollectQueryData соединяем все в одно целое:

if(PdhCollectQueryData(hQuery) == ERROR_SUCCESS)
{
cout<<"PdhCollectQueryData -ok-"<<endl;

PDH_FMT_COUNTERVALUE pdhValue;
DWORD dwType;

И последний шаг — получаем форматированное значение счетчика функцией
PdhGetFormattedCounterValue:

pdhStatus = PdhGetFormattedCounterValue(*phCounter,PDH_FMT_DOUBLE,&dwType,&pdhValue);
if(pdhStatus == ERROR_SUCCESS)
{
cout<<"PdhGetFormattedCounterValue -ok-"<<endl;

Выводим результат:

cout<<pdhValue.doubleValue<<endl;

}else{cout<<"Error PdhGetFormattedCounterValue"<<endl;}

}
else{cout<<"Error PdhCollectQueryData"<<endl;}

Небольшая задержка перед получением нового значения:

Sleep(500);
}
}else
{
cout<<"Error PdhAddCounter"<<endl;
if(pdhStatus == PDH_INVALID_ARGUMENT){cout<<"PDH_INVALID_ARGUMENT"<<endl;}
if(pdhStatus == PDH_CSTATUS_BAD_COUNTERNAME){cout<<"PDH_CSTATUS_BAD_COUNTERNAME"<<endl;}
if(pdhStatus == PDH_CSTATUS_NO_COUNTER){cout<<"PDH_CSTATUS_NO_COUNTER"<<endl;}
if(pdhStatus == PDH_CSTATUS_NO_COUNTERNAME){cout<<"PDH_CSTATUS_NO_COUNTERNAME"<<endl;}
if(pdhStatus == PDH_CSTATUS_NO_MACHINE){cout<<"PDH_CSTATUS_NO_MACHINE"<<endl;}
if(pdhStatus == PDH_CSTATUS_NO_OBJECT){cout<<"PDH_CSTATUS_NO_OBJECT"<<endl;}
if(pdhStatus == PDH_FUNCTION_NOT_FOUND){cout<<"PDH_FUNCTION_NOT_FOUND"<<endl;}
if(pdhStatus == PDH_INVALID_HANDLE){cout<<"PDH_INVALID_HANDLE"<<endl;}
if(pdhStatus == PDH_MEMORY_ALLOCATION_FAILURE){cout<<"PDH_MEMORY_ALLOCATION_FAILURE"<<endl;}
}

}else
{
cout<<"Error PdhMakeCounterPath: "<<endl;

if(pdhStatus == PDH_MORE_DATA){cout<<"PDH_MORE_DATA"<<endl;}
if(pdhStatus == PDH_INVALID_ARGUMENT){cout<<"PDH_INVALID_ARGUMENT"<<endl;}

}

}else{cout<<"Error PdhLookupPerfNameByIndex - 2"<<endl;}
}else
{
cout<<"Error PdhLookupPerfNameByIndex - 1"<<endl;
if(pdhStatus == PDH_MORE_DATA){cout<<"PDH_MORE_DATA"<<endl;}
if(pdhStatus == PDH_INVALID_ARGUMENT){cout<<"PDH_INVALID_ARGUMENT"<<endl;}
}
}else{cout<<"Error PdhOpenQuery"<<endl;}

Корректно завершаем обращение к PDH:

GlobalFree(phCounter);
PdhRemoveCounter(phCounter);
PdhCloseQuery(hQuery);

return 0;
}

Результат работы программы представлен на рисунке:

С помощью данного примера вы сможете контролировать значения основных
показателей производительности ваше компьютера, так же применение данной
технологии позволить расширить функциональные возможности ваших приложений.

Оставить мнение

Check Also

Конкурс хаков: пишем на PowerShell скрипт, который уведомляет о днях рождения пользователей Active Directory

В компаниях часто встречается задача уведомлять сотрудников о приближающихся днях рождения…