Mike_I
Участник
Offline
Пол:
Mike
|
|
« : 05-10-2006 13:50 » |
|
Привет, народ. Подскажите пути реализации задачи из сабжа. В инете и на форуме нарыл, что надо использовать функцию NtQuerySystemInformation. В MSDN'е написано через нее можно получить список всех процессов которые запущены на компе. Это понятно. Но как имея этот список вычислить загрузку процессора??? Или это делается вообще по другому?
|
|
« Последнее редактирование: 10-12-2007 18:01 от Алексей1153++ »
|
Записан
|
Nothing fails like success.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 05-10-2006 14:15 » |
|
кстати, тоже интересно было бы узнать...
|
|
|
Записан
|
|
|
|
Sands
Помогающий
Offline
|
|
« Ответ #2 : 05-10-2006 14:33 » |
|
вот что я в свое время нарыл и удачно использовал: #include <stdio.h> #include <pdh.h> #include <conio.h>
/*****************************************************************************/ /******** ********/ /******** не забудьте включить в проект "pdh.lib" ********/ /******** ********/ /******** Project -> Settings -> Link -> Object/Library Modules ********/ /******** ********/ /*****************************************************************************/
/*****************************************************************************/ /********** **********/ /********** PDH - performance data helper **********/ /********** **********/ /*****************************************************************************/
/************************** Описание наших функций ***************************/
#define PDH_ERROR -1
// Функция инициализирует PDH (performance data helper) PDH_STATUS pdh_Init (HQUERY &hQuery, HCOUNTER &hCounter);
// Функция возвращает в случае удачи загруженность проца, в противном случае PHG_ERROR (-1) int GetCPUUsage (HQUERY hQuery, HCOUNTER hCounter, PDH_STATUS &pdhStatus);
// Функция анинициализирует PDH void pdh_Uninit (HQUERY hQuery, HCOUNTER hCounter);
// Функция показывает сообщение об ошибке void ShowErrorMessage(PDH_STATUS pdhStatus);
// хмм... в названии функции все сказано! void begin();
/****************************************************************************/
void main(void) { begin(); printf(TEXT("Press any key to continue")); // нажмите "any key" на клавиатуре :P while (!_getch()); // ждем, пока юзверь не "клацнет" "any key" }
void begin() // хмм... в названии функции все сказано! { PDH_STATUS pdhStatus = 0;
HQUERY hQuery; HQUERY hCounter; int iUsage = 0; pdhStatus = pdh_Init(hQuery, hCounter); // инициализируем PDH
// если не произошел облом с иницализации PDH, то if ( pdhStatus == ERROR_SUCCESS ) { // пока юзверь не зажмет клавишу Esc, то while (GetKeyState(VK_ESCAPE) >= 0) { // получаем загруженность проца iUsage = GetCPUUsage(hQuery, hCounter, pdhStatus);
// если не произошла ошибка (т.е. не вернулось значение PHG_ERROR) if (iUsage != PDH_ERROR) printf("%3i%%\r\n", iUsage); // выводим значение else // а если произошла ошибка, то
// показываем сообщение, что произошла ошибка такая-то ShowErrorMessage(pdhStatus);
Sleep(500); // ждем 0.5 секунд(ы) }
// если юзверь все-таки клацнул Esc, то флаг ему в руки :) pdh_Uninit(hQuery, hCounter); // заканчиваем работу с PDH } else // если произошла ошибка при инициализации PDH ShowErrorMessage(pdhStatus); // показываем Еррорное сообщение }
void ShowErrorMessage(PDH_STATUS pdhStatus) // Сама функция показа сообщения об ошибке { LPSTR szMessage = NULL;
// грузим строку с ошибкой в szMessage. Память выделит функция FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle("PDH.DLL"), pdhStatus, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szMessage, 0, NULL);
printf("Error №%i: %s\r\n", pdhStatus, szMessage); // показываем ошибку
LocalFree(szMessage); // очищаем буфер }
PDH_STATUS pdh_Init(HQUERY &hQuery, HCOUNTER &hCounter) // инициализируем PDH { PDH_STATUS pdhResult = 0; TCHAR szCounterPath[1024]; DWORD dwPathSize = 1024; PDH_COUNTER_PATH_ELEMENTS pe; DWORD dwType = 0; pdhResult = PdhOpenQuery( NULL, 0, &hQuery ); // запрос на открытие PDH if ( pdhResult != ERROR_SUCCESS ) // если была ошибка, то return pdhResult; // выходим, возвращая номер ошибки
pe.szMachineName = 0l; pe.szObjectName = "Processor"; pe.szInstanceName = "_Total"; pe.szParentInstance = NULL; pe.dwInstanceIndex = 0; pe.szCounterName = "% Processor Time";
// создаем путь к счетчику PDH pdhResult = PdhMakeCounterPath(&pe, szCounterPath, &dwPathSize, 0);
if (pdhResult != ERROR_SUCCESS) // если была ошибка, то return pdhResult; // выходим, возвращая номер ошибки
// открываем счетчик PDH pdhResult = PdhAddCounter(hQuery, szCounterPath, 0, &hCounter);
if (pdhResult != ERROR_SUCCESS) // если была ошибка, то return pdhResult; // выходим, возвращая номер ошибки
// если дошли до этого места, то ошибки на 100% не было! return pdhResult; }
int GetCPUUsage(HQUERY hQuery, HCOUNTER hCounter, PDH_STATUS &pdhStatus) // получаем загруженность проца { DWORD dwType = 0;
// даем запрос на сборы инфы pdhStatus = PdhCollectQueryData(hQuery);
if (pdhStatus != ERROR_SUCCESS) // если была ошибка, то return PDH_ERROR; // выходим, возвращая ошибку
_PDH_FMT_COUNTERVALUE pfci; ZeroMemory(&pfci, sizeof(pfci)); // очищаем структуру pfci
// Получаем инфу о загруженности проца! pdhStatus = PdhGetFormattedCounterValue( hCounter, PDH_FMT_DOUBLE, &dwType, &pfci); if (pdhStatus != ERROR_SUCCESS) // если была ошибка, то return PDH_ERROR; // выходим, возвращая ошибку
return (int)pfci.doubleValue; // возвращаем загруженность проца! }
void pdh_Uninit(HQUERY hQuery, HCOUNTER hCounter) // анинициализация { PdhRemoveCounter(hCounter); // удаляем счетчик PdhCloseQuery(hQuery); // закрываем запрос }
правда есть тут одна загадка - все работает более менее корректно, однако первое возвращаемое значение почему-то равно 99% Однако иногда аналогичнве вещи наблюдаются и в родном Task managere винды
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Online
Пол:
Пролетал мимо
|
|
« Ответ #3 : 05-10-2006 20:15 » |
|
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Антон (LogRus)
|
|
« Ответ #4 : 06-10-2006 04:44 » |
|
|
|
|
Записан
|
Странно всё это....
|
|
|
Mike_I
Участник
Offline
Пол:
Mike
|
|
« Ответ #5 : 06-10-2006 06:54 » |
|
Привет, народ. Finch: Прочел то, что ты советовал. Вышел на функцию GetSystemTimes(LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME UserTime) lpIdleTime - A pointer to a FILETIME structure that receives the amount of time that the system has been idle. lpKernelTime - A pointer to a FILETIME structure that receives the amount of time that the system has spent executing in Kernel mode (including all threads in all processes, on all processors). lpUserTime - A pointer to a FILETIME structure that receives the amount of time that the system has spent executing in User mode (including all threads in all processes, on all processors). Первый параметр понятен - время простоя системы. А вот с двумя другими я не разобрался: Как понять: "время которое система провела работая в Режиме ядра(2 пар.)/Режиме пользователя(3 пар.)"? Что такое режим Ядра/Пользователя и главное как зная это время вычислить загрузку проца в текущий момент времени, пока это не ясно... : Осмелюсь предположмить, что сумма значений lpKernelTime и lpUserTime и будет выражать в процентах загрузку проца за 100 наносекундный интервал. Кто что об этом думает?
|
|
« Последнее редактирование: 06-10-2006 07:05 от Mike_I »
|
Записан
|
Nothing fails like success.
|
|
|
Mike_I
Участник
Offline
Пол:
Mike
|
|
« Ответ #6 : 06-10-2006 11:55 » |
|
Самое обидное, что у меня код содержащий функцию GetSystemTimes() не компилируется . Причем не компилируется даже если создать совершенно новый проект и вставить туда код примера из MSDN'а: http://www.microsoft.com/rus/msdn/magazine/archive/2003-06/core_api_full.aspКомпилятор всегда выдает ошибку: DevicedispDlgAuto.cpp(401) : error C3861: 'GetSystemTimes': identifier not found, even with argument-dependent lookup кто-нибудь знает как это исправить?
|
|
« Последнее редактирование: 10-12-2007 17:59 от Алексей1153++ »
|
Записан
|
Nothing fails like success.
|
|
|
Антон (LogRus)
|
|
« Ответ #7 : 06-10-2006 12:09 » |
|
вот эти Winbase.h Windows.h хедеры включены?
|
|
|
Записан
|
Странно всё это....
|
|
|
Mike_I
Участник
Offline
Пол:
Mike
|
|
« Ответ #8 : 06-10-2006 12:13 » |
|
да подключал и оба и без них и каждый по отдельности
|
|
« Последнее редактирование: 06-10-2006 12:18 от Mike_I »
|
Записан
|
Nothing fails like success.
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #9 : 06-10-2006 12:48 » |
|
А система у тебя какая? Операционка и среда? Client Requires Windows XP SP1. ... To compile an application that uses this function, define the _WIN32_WINNT macro as 0x0501 or later.
|
|
« Последнее редактирование: 06-10-2006 12:50 от Джон »
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
Mike_I
Участник
Offline
Пол:
Mike
|
|
« Ответ #10 : 06-10-2006 12:52 » |
|
Система: WinXP Prof SP2 + куча всяких исправлений. Среда: VS .net
|
|
« Последнее редактирование: 06-10-2006 13:37 от Джон »
|
Записан
|
Nothing fails like success.
|
|
|
Mike_I
Участник
Offline
Пол:
Mike
|
|
« Ответ #11 : 06-10-2006 13:03 » |
|
пробовал - эффекта никакого тока я перед этим делал #undef _WIN32_WINNT а то вылазит Error redifination
|
|
|
Записан
|
Nothing fails like success.
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #12 : 06-10-2006 13:36 » |
|
) Всё в порядке. Ты только _WIN32_WINNT изменил? А как же остальные? Те система у тебя всё ещё четвёрка и ИЕ (comctrl-версия) тоже. Кстати undef не нужен - она же у тебя в самом верху уже есть просто значения измени. В общем вот так делай: #ifndef WINVER // Lassen Sie die Verwendung von Features spezifisch für Windows 95 und Windows NT 4 oder später zu. #define WINVER 0x0501 // Ändern Sie den entsprechenden Wert, um auf Windows 98 und mindestens Windows 2000 abzuzielen. #endif
#ifndef _WIN32_WINNT // Lassen Sie die Verwendung von Features spezifisch für Windows NT 4 oder später zu. #define _WIN32_WINNT 0x0501 // Ändern Sie den entsprechenden Wert, um auf Windows 98 und mindestens Windows 2000 abzuzielen. #endif
#ifndef _WIN32_WINDOWS // Lassen Sie die Verwendung von Features spezifisch für Windows 98 oder später zu. #define _WIN32_WINDOWS 0x0501 // Ändern Sie den entsprechenden Wert, um auf mindestens Windows Me abzuzielen. #endif
#ifndef _WIN32_IE // Lassen Sie die Verwendung von Features spezifisch für IE 4.0 oder später zu. #define _WIN32_IE 0x0501 // Ändern Sie den entsprechenden Wert, um auf mindestens IE 5.0 abzuzielen. #endif
зы Немного подчистил сообщения
|
|
« Последнее редактирование: 06-10-2006 13:39 от Джон »
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
alvahtin
Гость
|
|
« Ответ #13 : 22-03-2009 13:52 » |
|
вот что я в свое время нарыл и удачно использовал: #include <stdio.h> #include <pdh.h> #include <conio.h>
Что-то в C++ Builder не получаетцо . В этом месте: // создаем путь к счетчику PDH pdhResult = PdhMakeCounterPath(&pe, szCounterPath, &dwPathSize, 0); Выдает код ошибки 0xC0000BBDL, что означает PDH_INVALID_ARGUMENT . Не понятно, везде говорят, что все у них получается, а тут не работает... ОС Windows XP.
|
|
|
Записан
|
|
|
|
alvahtin
Гость
|
|
« Ответ #14 : 22-03-2009 15:09 » |
|
Нашел причину! 1. pe.szMachineName = 0l; pe.szObjectName = "Processor"; pe.szInstanceName = "_Total"; pe.szParentInstance = NULL; pe.dwInstanceIndex = 0; pe.szCounterName = "% Processor Time";
Не понимает. Нужно написать по русски: pe.szMachineName = 0l; pe.szObjectName = "Процессор"; pe.szInstanceName = "_Total"; pe.szParentInstance = NULL; pe.dwInstanceIndex = (DWORD)-1; pe.szCounterName = "% Загруженности процессора";
а еще лучше: TCHAR szObjectName[256], szCounterName[256], szPath[1024]; DWORD dwSize;
pdhStatus = PdhLookupPerfNameByIndex(NULL, 238, szObjectName, &dwSize);//-1 pdhStatus = PdhLookupPerfNameByIndex(NULL, 6, szCounterName, &dwSize);//-2
pe.szMachineName = 0l; pe.szObjectName = szObjectName; pe.szInstanceName = "_Total"; pe.szParentInstance = NULL; pe.dwInstanceIndex = (DWORD)-1; pe.szCounterName = szCounterName; Тогда все работает как часы
|
|
|
Записан
|
|
|
|
|