This is implemented as a small, simple static library that runs a separate thread to periodically collect the necessary information, calculate the CPU and memory usage, and pass them to a user-supplied callback. Instead of dealing with the complexities of PDH or a lower-level API, this code derives the CPU usage from the GetProcesssTimes function and the memory usage from the GetProcessMemoryInfo function. The test app is intended as a simple method of providing a controllable CPU usage, so the usage returned by the library can be compared to the usage reported by Task Manager and Process Monitor, across a range of values.
Edit: Added the monitor.inc that I left out of the attachment.
[attachment deleted by admin]
Good stuff :U
Thanks mate
Nice work :) seems pretty accurate, is better than the slow crappy pdh code I got somewhere.
nice and easy to adapt... i wanted the page fault counter to be available and that costed me few minutes to include.
many thanks :U
doesn't report cpu usage for each core though.. does it?
I'm not sure what it would report running on a multi-core system because I have no multi-core hardware available (or at least not conveniently available). I think it could be restricted to running on a given core with SetProcessAffinityMask. MonitorInit already gets the process handle, so the modification could be as simple as adding an affinity mask parameter and passing it to SetProcessAffinityMask.
you can restrict execution to a single core by using the Task Manager (right-click on the process - Set Affinity)
thats not what i meant.. i meant its reporting overall cpu usage, not usage per core :)
i knew that, of course
i meant for a simple quick test of the function
i don't have to tell Michael how to use SetProcessAffinityMask - lol
but, many do not know you can set it manually
EDIT
he has a single-core machine and may want some help testing
The Windows 2000 Task Manager allows you to control the process priority, but there is no support for the affinity mask.
it may be that it just doesn't show up on a single-core, Michael
correct...
SetProcessAffinityMask Function
Minimum supported client Windows 2000 Professional
Minimum supported server Windows 2000 Server
Header Winbase.h (include Windows.h)
Library Kernel32.lib
DLL Kernel32.dll
you won't see affinity stuff unless you have >1 core's, which explains why you won't see it in task manager
taskmanager can definately show cpu usage per core, just i think its undocumented, in my own code i can
see the overall cpu utilization but not a core by core breakdown.. and i've yet to find the api for it, knowing
my luck its probably undocumented...
if i find it i'll post here :)
good luck evlncrn8 :U
so far, i haven't seen any software that breaks it down that way - i'll keep my eyes open
just figured it out :)
NtQuerySystemInformation using SystemProcessorPerformanceInformation class (0x08) is the key...
the struct you pass should be sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*sysinf.dwNumberOfProcessors)
where sysinf.dwNumberOfProcessors is obtained from a GetSystemInfo call
this returns the timing for all the processors on the system (using the size of the struct *1 will just return processor #0.. and none of the others)...
easiest way would also be to make a buffer of sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) *32
(cos there can only be 32 max processors afaik.. course, this may change in the future)...
then you do the processing as normal
call once, fill an 'old' struct.. call again, filling the 'new' struct'
do the math on the differential between each one...
advance the struct pointers to read the next data for the processor(s)...
loop.. repeat with a little sleep inbetween...
job done :) now im off to update my code in protection id so it reports each core usage
oh and taskmanager breaks it down that way... just required a little bit of reversing and figuring out how it did its stuff
here's the proof of concept code.. its in c.. prototype.. but works.. .needs some tweaking but it shows how to do it
//---------
#include "stdio.h"
#include "windows.h"
//---------
typedef DWORD (__stdcall *LPFN_NtQuerySystemInformation)(DWORD, PVOID, DWORD, PDWORD);
#define SystemProcessorPerformanceInformation 0x8
//---------
#pragma pack(push,8)
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER DpcTime;
LARGE_INTEGER InterruptTime;
ULONG InterruptCount;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION,
*PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
#pragma pack(pop)
//---------
int main(int argc, char* argv[]) {
SYSTEM_INFO systeminfo;
unsigned long bytesreturned;
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION spi_old[32];
memset(spi_old,0,sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*32);
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION spi[32];
memset(spi,0,sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*32);
LPFN_NtQuerySystemInformation ntquerysysteminformation =(LPFN_NtQuerySystemInformation) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
if(!ntquerysysteminformation) {
printf("\n*** no ntquerysysteminformation api?.. bugger");
return -1;
}
GetSystemInfo(&systeminfo);
printf("\n[i] Processor Count: %d\n",systeminfo.dwNumberOfProcessors);
ntquerysysteminformation(SystemProcessorPerformanceInformation,spi_old, (sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*systeminfo.dwNumberOfProcessors),&bytesreturned);
Sleep(500);
ntquerysysteminformation(SystemProcessorPerformanceInformation,spi, (sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*systeminfo.dwNumberOfProcessors),&bytesreturned);
for(int cpuloopcount = 0; cpuloopcount < systeminfo.dwNumberOfProcessors; cpuloopcount++) {
BYTE cpuusage = (BYTE) (100 - (((spi[cpuloopcount].IdleTime.QuadPart - spi_old[cpuloopcount].IdleTime.QuadPart) * 100) / \
((spi[cpuloopcount].KernelTime.QuadPart + spi[cpuloopcount].UserTime.QuadPart) - (spi_old[cpuloopcount].KernelTime.QuadPart + spi_old[cpuloopcount].UserTime.QuadPart))));
printf("\n[i] CPU %02d: = %0d%%",cpuloopcount, cpuusage);
}
return 0;
}
rename .zip to .rar then unrar it.. dunno why rar's arent supported here but i really couldn't be bothered making a zip...
[attachment deleted by admin]
Cool stuff, good work evil incarnate :toothy