Reputation: 105
I found this code on google that calculate of % of usage of current process on win10,but what i'm looking for is a list of % of CPU Usage of every process. I use GetCurrentProcess() to have the handle of the current process. Is there a way to retrieve the handle of every processes?i'm working on a code that lists running process and calculate usage memory for everyone. Then i need to calculate cpu usage for everyone but i didn't find anything on google.
static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
static int numProcessors;
static HANDLE self;
void init(){
SYSTEM_INFO sysInfo;
FILETIME ftime, fsys, fuser;
GetSystemInfo(&sysInfo);
numProcessors = sysInfo.dwNumberOfProcessors;
GetSystemTimeAsFileTime(&ftime);
memcpy(&lastCPU, &ftime, sizeof(FILETIME));
self = GetCurrentProcess();
GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
memcpy(&lastSysCPU, &fsys, sizeof(FILETIME));
memcpy(&lastUserCPU, &fuser, sizeof(FILETIME));
}
double getCurrentValue(){
FILETIME ftime, fsys, fuser;
ULARGE_INTEGER now, sys, user;
long double percent;
GetSystemTimeAsFileTime(&ftime);
memcpy(&now, &ftime, sizeof(FILETIME));
GetProcessTimes(GetCurrentProcess(), &ftime, &ftime, &fsys, &fuser);
memcpy(&sys, &fsys, sizeof(FILETIME));
memcpy(&user, &fuser, sizeof(FILETIME));
percent = (sys.QuadPart - lastSysCPU.QuadPart) +
(user.QuadPart - lastUserCPU.QuadPart);
percent /= (now.QuadPart - lastCPU.QuadPart);
percent /= numProcessors;
lastCPU = now;
lastUserCPU = user;
lastSysCPU = sys;
return percent * 100;
}
I'm able to have the list of all running processes but i'm looking for to
calculate cpu usage for every process.
Suggestions?
Upvotes: 0
Views: 1840
Reputation: 33716
ok, for effective coding this task need use NtQueryInformationProcess
with SystemProcessInformation
info class. we got here array of SYSTEM_PROCESS_INFORMATION
. here we already have:
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
when in PROCESSENTRY32
no this members. toolhelp functions simply drop this member. without it we need open every process, call GetProcessTimes
, etc. with NtQueryInformationProcess
all become much more effective and simply. general idea - we need maintain list of processes, and periodic call NtQueryInformationProcess
for add new created processes and remove died.
// for debug only 0 <= cpuUsage <= 1000
void PrintCpuUsage(ULONG cpuUsage, PCUNICODE_STRING Name)
{
ULONG p = cpuUsage / 10;
DbgPrint("%02u.%u %wZ\n", p, cpuUsage - p * 10, Name);
}
struct PROCESS_ENTRY : LIST_ENTRY, UNICODE_STRING
{
LARGE_INTEGER _CreateTime, _RunTime;
union {
LARGE_INTEGER _Delta;
ULONG _cpuUsage;
};
HANDLE _UniqueProcessId;
HANDLE _InheritedFromUniqueProcessId;
BOOLEAN _bEnumerated;
PROCESS_ENTRY()
{
RtlInitUnicodeString(this, 0);
InitializeListHead(this);
_RunTime.QuadPart = 0;
_UniqueProcessId = 0;
}
~PROCESS_ENTRY()
{
DbgPrint("--%08x(%08x) %wZ\n", _UniqueProcessId, _InheritedFromUniqueProcessId, static_cast<UNICODE_STRING*>(this));
RtlFreeUnicodeString(this);
RemoveEntryList(this);
}
NTSTATUS Init(PSYSTEM_PROCESS_INFORMATION pspi)
{
_UniqueProcessId = pspi->UniqueProcessId;
_InheritedFromUniqueProcessId = pspi->InheritedFromUniqueProcessId;
_CreateTime = pspi->CreateTime;
DbgPrint("++%08x(%08x) %wZ\n", _UniqueProcessId, _InheritedFromUniqueProcessId, &pspi->ImageName);
return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &pspi->ImageName, this);
}
LONGLONG UpdateProcess(PSYSTEM_PROCESS_INFORMATION pspi)
{
_bEnumerated = TRUE;
pspi->KernelTime.QuadPart += pspi->UserTime.QuadPart;
_Delta.QuadPart = pspi->KernelTime.QuadPart - _RunTime.QuadPart;
_RunTime.QuadPart = pspi->KernelTime.QuadPart;
return _Delta.QuadPart;
}
void CalcCpuUsage(LONGLONG QuadPart)
{
_bEnumerated = FALSE;
_cpuUsage = (ULONG)((_Delta.QuadPart * 1000) / QuadPart );
if (_cpuUsage && _UniqueProcessId)
{
PrintCpuUsage(_cpuUsage, this);
}
}
};
struct PROCES_LIST : public LIST_ENTRY
{
LIST_ENTRY _ListHead;
PROCESS_ENTRY IdleProcess;
BOOL _bValid;
PROCES_LIST()
{
InitializeListHead(&_ListHead);
_bValid = FALSE;
}
LONGLONG UpdateOrAddNewProcess(PSYSTEM_PROCESS_INFORMATION pspi);
void RemoveDiedEntries(LONGLONG QuadPart);
void EnumPro();
~PROCES_LIST()
{
RemoveDiedEntries(0);
}
};
LONGLONG PROCES_LIST::UpdateOrAddNewProcess(PSYSTEM_PROCESS_INFORMATION pspi)
{
PROCESS_ENTRY* pe;
PLIST_ENTRY head = &_ListHead, entry = head;
HANDLE UniqueProcessId = pspi->UniqueProcessId;
while ((entry = entry->Flink) != head)
{
pe = static_cast<PROCESS_ENTRY*>(entry);
if (pe->_UniqueProcessId == UniqueProcessId && pe->_CreateTime.QuadPart == pspi->CreateTime.QuadPart)
{
return pe->UpdateProcess(pspi);
}
}
if (pe = new PROCESS_ENTRY)
{
if (0 <= pe->Init(pspi))
{
InsertTailList(head, pe);
return pe->UpdateProcess(pspi);
}
delete pe;
}
return 0;
}
void PROCES_LIST::RemoveDiedEntries(LONGLONG QuadPart)
{
PLIST_ENTRY head = &_ListHead, entry = head->Flink;
while (entry != head)
{
PROCESS_ENTRY* pe = static_cast<PROCESS_ENTRY*>(entry);
entry = entry->Flink;
if (pe->_bEnumerated)
{
pe->CalcCpuUsage(QuadPart);
}
else
{
delete pe;
}
}
}
void PROCES_LIST::EnumPro()
{
ULONG cb = 0, rcb = 0x10000;
PVOID stack = alloca(guz);// volatile UCHAR guz;
union {
PVOID buf;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
NTSTATUS status;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &rcb)))
{
LONGLONG QuadPart = 0;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
if (pspi->UniqueProcessId)
{
QuadPart += UpdateOrAddNewProcess(pspi);
}
else
{
QuadPart += IdleProcess.UpdateProcess(pspi);
}
} while (NextEntryOffset = pspi->NextEntryOffset);
RemoveDiedEntries(QuadPart);
IdleProcess.CalcCpuUsage(QuadPart);
if (_bValid)
{
static UNICODE_STRING empty;
PrintCpuUsage(1000 - IdleProcess._cpuUsage, &empty);
}
else
{
_bValid = TRUE;
}
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}
Upvotes: 2