The following is a very basic process CPU load determiner.
It is the result of a conversation between dodicat and myself in another thread.
It would be nice if we supplied the process name and the code did the rest. However, as is we have to supply the process id of the target process and that is that I mean by 'very basic'. That and the fact the the algorithm employed is very simple.
The algorithm simply determines the ratio of 'Kernel time + User time' and the interval of successive 'firings' of timeSetEvent.
It's intended use is for monitoring our own 'master pieces'. I have tried on other sources such as explorer.exe and it even worked on 'Process Hacker'. However, for many the OpenProcess API failed and we would need to get involved in permissions. We don't need that for it's intended use.
So where do we get the process id from? Well, one place is the Details tab of Task Manager.
The console displays CPU Load, Max Load and 'Total CPU Time'.
Do not close with the Close button. Instead, press Enter. Monitoring will then stop followed by a clean up to avoid a memory leak. Press ENTER again to exit - of which we are reminded.
I could't fathom out how to get the number of CPU cores. I would get there in the end but dodicat had already been there so I 'pinched' his code. The cheque is in the post, dodicat - the pigeon is called Gladis. Just give her a wee dram of Scotch. Don't get too close, she pecks.
The following code appears to be in agreement with Task Manager. Not so with Process Hacker which tends to give higher loads. I prefer Process Hacker, much more information available. Process Hacker can display total CPU time and the following code agreed exactly. At least this proved that the code was monitoring the correct target. <smile>
The bi files with regard Windows APIs sticks to MSDN's datatypes like glue so I do the same. This helps when converting MSDN's examples to FreeBASIC. However, I had an issue with Dword_Ptr. A text search of the bi files for Dword_Ptr found 24 files and I eventually found 'type DWORD_PTR as ULONG_PTR'. Another text search for Ulong_Ptr found 45 files and I eventually found 'type ULONG_PTR as ulongint'. So, Dword_Ptr is not a pointer. I managed to get thing working but it was a pain.
As is I don't think the code is much use. If we have to open Task Manger to get a target's process id we may as well leave it open to monitor the CPU load. Anyway, I posted the code should anyone have any ideas.
Code: Select all
#include once "windows.bi"
#include once "win\winbase.bi"
#Include Once "win\mmsystem.bi"
Dim As Uint_Ptr TimerID
Dim As Longint Dummy, KernelTime, UserTime
Dim As Dword ProcessId, Result
Dim As Handle hProcess
Dim As WinBool Inherit
Dim Shared As Long cores
Function loadfile(file As String) As String 'By dodicat
Var f=Freefile
Open file For Binary Access Read As #f
Dim As String text
If Lof(1) > 0 Then
text = String(Lof(f), 0)
Get #f, , text
End If
Close #f
Return text
End Function
Sub GetCPULoad( uTimerID As Uint, uMsg As Uint, dwUser As Handle, dw1 As Dword_Ptr, dw2 As Dword_Ptr )
Static As boolean FirstInstance = true
Static As Longint LastKernelTime, LastUserTime, LastCurrentTime
Dim As Longint Dummy, KernelTime, UserTime, CurrentTime
Dim As Dword Result
Dim As Double CPULoad
Static As Double MaxLoad
Dim hProcess As Handle
If FirstInstance = true Then
GetSystemTimeAsFileTime ( Cast(LPFILETIME, @LastCurrentTime) )
Result = GetProcessTimes( dwUser, Cast(LPFILETIME, @Dummy), Cast(LPFILETIME, @Dummy), Cast(LPFILETIME, @LastKernelTime), Cast(LPFILETIME, @LastUserTime ) )
FirstInstance = false
Else
GetSystemTimeAsFileTime ( Cast(LPFILETIME, @CurrentTime ) )
Result = GetProcessTimes( dwUser, Cast(LPFILETIME, @Dummy), Cast(LPFILETIME, @Dummy), Cast(LPFILETIME, @KernelTime), Cast(LPFILETIME, @UserTime ) )
CPULoad = 100*(KernelTime - LastKernelTime + UserTime - LastUserTime)/( CurrentTime - LastCurrentTime )/cores
Locate 5, 20
Print Using "CPU Load: ###.###";CPULoad
Locate 7, 20
Print Using "Max Load: ###.###";MaxLoad
Locate 9, 20
Print Using "Total CPU Time: ###.### seconds";(KernelTime + UserTime)/10^7
End If
LastKernelTime = KernelTime
LastUserTime = UserTime
LastCurrentTime = CurrentTime
If CPULoad > MaxLoad Then MaxLoad = CPULoad
End Sub
Input "Target's process id: ";ProcessID
Cls
Print " Press ENTER to stop monitoring"
Shell "echo %NUMBER_OF_PROCESSORS% >tmpcores.txt"
cores=Valint(loadfile("tmpcores.txt"))
hProcess = OpenProcess( PROCESS_ALL_ACCESS, Inherit, Cast(Dword, ProcessId ) )
If hProcess = 0 Then
Print
Print " Open process failed"
Goto TidyUp
End If
Result = GetProcessTimes( hProcess, Cast(LPFILETIME, @Dummy), Cast(LPFILETIME, @Dummy), Cast(LPFILETIME, @KernelTime), Cast(LPFILETIME, @UserTime ) )
If Result = 0 Then
Print
Print " Get process times failed"
Goto TidyUp
End If
TimerID = timeSetEvent( 500, 0, Cast( LPTIMECALLBACK, @GetCPUload ), Cast( Dword_Ptr, hProcess ), TIME_PERIODIC )
Sleep
TidyUp:
If TimerID <> 0 Then timeKillEvent TimerID
If hProcess <> 0 Then CloseHandle hProcess
Locate 14
Print " Press ENTER to exit"
Sleep