I know this is quite an old post to respond to...
I ran into a situation where i had to record the CPU usage (over a long time duration) of a process which has multiple instances runnin at the same time.
I have no idea of kernel32.dll and the funtions in it. I have just merged 2 scripts I found on the Forum (1 of which is the SKAN's script above). The second script i used is
http://www.autohotkey.com/forum/topic28464.html&highlight=process+list
The merged script gives me a log file, with Process load of each instance followed by the total CPU usage, every 250 mSec.
I just want to ensure that after all the changes i made, the script still generates accurate results? And I am also sure the script can be optimised further.
Any Ideas???? Can someone atleast confirm the correctness???
usage (on the command prompt): <filename.ahk> processname logfile.txt
Code:
#Persistent
#SingleInstance, Force
CoordMode, ToolTip, Screen
IfNotEqual, 0, 2
{
Msgbox, Invalid Arguments`nUsage: RecordCPUusage.exe <Process Name> <Filename.txt>
ExitApp
}
Process, Exist, %1%
PID := errorLevel
If PID = 0
{
Msgbox, Process does not exist. Please check the process name.
ExitApp
}
OUTPUTFILE = %2%
d = `n ; string separator
s := 4096 ; size of buffers and arrays (4 KB)
Process, Exist ; sets ErrorLevel to the PID of this running script
; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
VarSetCapacity(ti, 16, 0) ; structure of privileges
InsertInteger(1, ti, 0, 4) ; one entry in the privileges array...
; Retrieves the locally unique identifier of the debug privilege:
DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege", "UIntP", luid)
InsertInteger(luid, ti, 4, 8)
InsertInteger(2, ti, 12, 4) ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
; Update the privileges of this process with the new access token:
DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false, "UInt", &ti, "UInt", 0, "UInt", 0, "UInt", 0)
DllCall("CloseHandle", "UInt", h) ; close this process handle to save memory
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll") ; increase performance by preloading the libaray
s := VarSetCapacity(a, s) ; an array that receives the list of process identifiers:
DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
PROCESSIDCOUNT = 0
Loop, % r // 4 ; parse array for identifiers as DWORDs (32 bits):
{
id := ExtractInteger(a, A_Index * 4)
; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id)
VarSetCapacity(m, s) ; an array that receives the list of module handles:
DllCall("Psapi.dll\EnumProcessModules", "UInt", h, "UInt", &m, "UInt", s, "UIntP", r)
VarSetCapacity(n, s, 0) ; a buffer that receives the base name of the module:
e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", m, "Str", n, "Chr", s)
DllCall("CloseHandle", "UInt", h) ; close process handle to save memory
If n ; if image is not null add to list:
{
ifequal, n,%1%
{
PROCESSIDCOUNT += 1
PROCESSIDLIST%PROCESSIDCOUNT% = %id%
}
}
}
DllCall("FreeLibrary", "UInt", hModule) ; unload the library to free memory
FileAppend, %PROCESSIDCOUNT% process(s) found by the name %1%.`n, %OUTPUTFILE%
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4) ; See DllCall for details.
{
Loop %pSize% ; Build the integer by adding up its bytes.
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result ; Signed vs. unsigned doesn't matter in these cases.
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
Loop %pSize% ; Copy each byte in the integer into the structure as raw binary data.
DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
SetTimer, ShowToolTip
Return
ShowToolTip:
FileAppend, %A_DD% %A_MMM% %A_YYYY% %A_Hour%:%A_Min%:%A_Sec%.%A_MSec%, %OUTPUTFILE%
Loop %PROCESSIDCOUNT%
{
element := PROCESSIDLIST%A_Index%
PrLoad := Round( GetProcessTimes(element, A_Index),2)
FileAppend, `tProcess load (ID: %element%) = %PrLoad%`%, %OUTPUTFILE%
}
TotCPULoad := GetSystemTimes()
FileAppend, `tTotal CPU Load = %TotCPULoad%`%`n, %OUTPUTFILE%
Return
GetProcessTimes( PID=0, IndexValue=1 )
{
global
hProc := DllCall("OpenProcess", "Uint", 0x400, "int", 0, "Uint", pid)
DllCall("GetProcessTimes", "Uint", hProc, "int64P", CreationTime, "int64P", ExitTime, "int64P", newKrnlTime, "int64P", newUserTime)
DllCall("CloseHandle", "Uint", hProc)
PROCESSCPUUSAGE := (newKrnlTime - oldKrnlTime%IndexValue% + newUserTime - oldUserTime%IndexValue%)/10000000 * 100
oldKrnlTime%IndexValue% := newKrnlTime
oldUserTime%IndexValue% := newUserTime
Return PROCESSCPUUSAGE
}
GetSystemTimes() ; Total CPU Load
{
Static oldIdleTime, oldKrnlTime, oldUserTime
Static newIdleTime, newKrnlTime, newUserTime
oldIdleTime := newIdleTime
oldKrnlTime := newKrnlTime
oldUserTime := newUserTime
DllCall("GetSystemTimes", "int64P", newIdleTime, "int64P", newKrnlTime, "int64P", newUserTime)
Return (1 - (newIdleTime-oldIdleTime)/(newKrnlTime-oldKrnlTime + newUserTime-oldUserTime)) * 100
}