I put this script together to replace the system monitor "CoolMon."
Everything that I was monitoring with CoolMon can be monitored using AHK.... so its bye bye CoolMon.
Details are in the code...
Update: 25/4/07
Top process info AND Cpu info both now gathered from Task Manager for better synchronisation.
Task Manager now restarts if shut down while script is running.
Changed drive space labels to from GB to MB!!
Removed surplus code.
Update: 25/4/07
Removed the need for the user to manually set the columns in TM. The script now saves the users preferences from the registry and replaces them with the two columns needed by the script. The original preferences are restored on exit.
NOTE: If TM is used while the script is running and columns are added to the listview, it is quicker to close TM and have the script restart it rather than removing the added columns.
Update: 27/4/07
Made the gui look a bit nicer.
Adjusted the layout.
Added tray icon.
Added invisible drag bar at top of gui.
Update: 29/4/07
Incorporated drive R/W monitor into drive space section of gui (drive label colour change = "disk read", drive letter colour change = "disk write")
Added net traffic visual indicator to gui and tray icon.
Added the ability (tray menu) to disable individual monitors.
Code:
;____________________
; \____SysMon_____/
; Coded by MsgBox. Last Edit:- 29/04/07
; This little app is composed of a collection of scripts found on the forum and
; merged and into one. Is yours there?....hmmmm? Well, thank you very much.
; It is designed to sit pinned to the desktop and displays various system
; statistics:
;
; Uptime, Top Process, Cpu usage, number of running processes, memory, IP Address,
; network statistics, drive statistics and a drive read/write monitor.
; Gui colour, screen position and font colours can be changed to suit your desktop.
; Though initially pinned to the desktop, the gui can be un-pinned via the system
; tray menu as an always on top display and moved by clicking and dragging at the
; top of the gui or the top of the drive label column.
; Double clicking the tray icon also un-pins the gui.
#SingleInstance Force
PID:=DllCall("GetCurrentProcessId")
DriveGet driveList, list, fixed
Loop Parse, drivelist
gbHt:=A_Index ; Count no. of drives for GroupBox hight.
DetectHiddenWindows On
SetTimer UpdateMem, 1000
SetTimer TopProcess, 50
SetTimer NetMeter
SetTimer ScanDrv,50
SetTimer UpdateDrives, 5000
LabelColour = Aqua ; Set label colour.
InfoColour = Lime ; Set info colour.
GuiColour = #00313031 ; Set Gui colour.
DriveMonColour = FFFF00 ; Set drive r/w colour.
GuiXPos = 805 ; Gui horizontal position.
GuiYPos = 21 ; Gui vertical position.
VarSetCapacity( IdleTicks, 2*4 )
VarSetCapacity( memstatus, 100 )
Gui Margin, 5, 5
Gui Color, %GuiColour%
Gui +LastFound +ToolWindow -SysMenu -Caption
; Up time.
Gui Add, GroupBox, w210 h70 Section
Gui Add, Text, x0 y0 w210 h20 guiMove +BackgroundTrans ; Click and drag.
Gui Font, s8 c%InfoColour%, Tahoma
Gui Add, Text, xs+10 ys+15 c%LabelColour% guiMove, Up Time:
Gui Add, Text, x+2 w50 vup, %t_UpTime%
; Cpu and memory.
Gui Add, Text, x+19 c%LabelColour%, Processes:
Gui Add, Text, x+2 w20 vnops, %nop%
Gui Add, Text, xs+10 yp+20 c%LabelColour%, Top Process:
Gui Add, Text, x+2 w75 vtopp , %tp%
Gui Add, Text, x+2 c%LabelColour%, CPU:
Gui Add, Text, x+2 w30 vCpu
Gui Add, Text, xs+22 yp+15 c%LabelColour%, RAMUsed:
Gui Add, Text, x+2 w125 vMem
; Network info.
Gui Font
Gui Add, GroupBox, xm yp+16 Section w210 h70
Gui Add, GroupBox, xp yp w26 h32
Gui Font, s8 c%InfoColour%, Tahoma
Gui Add, Picture, xs+7 yp+13 w15 h15 Icon63 vnetIcon, NetShell.dll
Gui Add, Text, x+25 yp+2 c%LabelColour%, IP Address:
Gui Add, Text, x+5, %a_ipaddress1%
Gui Add, Text, xs+10 yp+20 c%LabelColour%, Net Traffic:
Gui Add, Text, x+5 w50 h16 vkbps, 3
Gui Add, Text, x+0 c%LabelColour%, Down:
Gui Add, Text, x+5 w50 h16 vRecv, 2
Gui Add, Text, xs+37 yp+15 c%LabelColour%, Total:
Gui Add, Text, x+5 w50 h16 vband, 4
Gui Add, Text, x+13 c%LabelColour%, Up:
Gui Add, Text, x+5 w50 h16 vSent, 1
; Hard drive info.
Gui Font
Gui Add, GroupBox, xm yp+16 Section w210 R%gbHt%
Gui Font, s8 c%InfoColour%, Tahoma
Gui Add, Text, xs+10 ys+15 w92 guiMove
Gui Add, Text, x+5 c%LabelColour% section, Free/MB Total/MB
GoSub GetDrives
Set_Parent_by_class("Progman","") ; Pin Gui to desktop.
Gui Show,NoActivate x%GuiXPos% y%GuiYPos%,SysMon
GoSub StartTM
WinHide ahk_pid %PID% ; Hide Task MAnager.
Gosub TraySetup
If GetIfTable(tb)
ExitApp
Loop, % DecodeInteger(&tb) {
If DecodeInteger(&tb + 4 + 860 * (A_Index - 1) + 544) < 4
|| DecodeInteger(&tb + 4 + 860 * (A_Index - 1) + 516) = 24
Continue
ptr := &tb + 4 + 860 * (A_Index - 1)
Break
}
IfLess, ptr, 1, ExitApp
OnExit Out ; Quit Task Manager.
Return
ScanDrv:
SetTimer,ScanDrv,Off
Loop,% DrvCount
{
VarSetCapacity(dp%A_Index%,88)
DllCall("DeviceIoControl",Uint,hDrv%A_Index%,Uint,0x00070020,Uint,0,Uint,0
,Uint,&dp%A_Index%,Uint,88,UintP,nReturn,Uint,0)
nReadCount%A_Index% := DecodeInteger(&dp%A_Index% + 40)
nWriteCount%A_Index% := DecodeInteger(&dp%A_Index% + 44)
_= Case Writing @ y%A_Index%
If (nWriteCount%A_Index% <> _nWriteCount_%A_Index%)
{
_nWriteCount_%A_Index% := nWriteCount%A_Index%
Gui Font, Bold c%DriveMonColour%
GuiControl Font, y%A_Index%
}
Else {
Gui Font, norm c%LabelColour%
Guicontrol Font, y%A_Index%
}
_= Case Reading @ x%A_Index%
If (nReadCount%A_Index% <> _nReadCount_%A_Index%)
{
_nReadCount_%A_Index% := nReadCount%A_Index%
Gui Font, Bold c%DriveMonColour%
GuiControl Font, x%A_Index%
}
Else {
Gui Font, norm c%LabelColour%
Guicontrol Font, x%A_Index%
}
}
SetTimer,ScanDrv,On
Return
GetDrives:
Loop Parse, driveList
{
l := A_LoopField
Letter = %A_LoopField%:\
DriveGet Cap_%l%, Cap, %Letter%
Cap := number(Cap_%l%)
DriveSpaceFree Free_Space, %Letter% ;Get the free space in each drive
Free_Space := number(Free_Space)
DriveGet, label_%l%, label, %Letter%
StringUpper label, label_%l%, T
Gui Add, Text, xm+20 ys+15 w57 c%LabelColour% vx%A_Index%, %label%
Gui Add, Text, x+2 w25 c%LabelColour% vy%A_Index%, %Letter%
Gui Add, Text, x+2 w45 c%InfoColour% vFree_%l%, %Free_Space%
Gui Add, Text, x+2 w45 c%InfoColour% section, %Cap%
}
Loop Parse,driveList
{
DrvCount ++
Drv%A_Index% := a_Loopfield
CurDrv:= "\\.\" Drv%A_Index% ":"
hDrv%A_Index% := DllCall("CreateFile",Str,CurDrv,Uint,0,Uint,3,Uint,0,Uint,3,Uint,0,Uint,0)
}
Return
UpdateMem:
; Up time.
t_TimeFormat := "HH:mm:ss"
t_StartTime := ; Clear variable = A_Now
t_UpTime := A_TickCount // 1000 ; Elapsed seconds since start
t_StartTime += -t_UpTime, Seconds ; Same as EnvAdd with empty time
FormatTime t_NowTime, , %t_TimeFormat% ; Empty time = A_Now
FormatTime t_StartTime, %t_StartTime%, %t_TimeFormat%
t_UpTime := % t_UpTime // 3600 ":" mod(t_UpTime // 60, 60) ;":" mod(t_UpTime, 60)
GuiControl,, up, %t_UpTime%
; Memory.
DllCall("kernel32.dll\GlobalMemoryStatus", "uint",&memstatus)
mem := *( &memstatus + 4 ) ; last byte is enough, mem = 0..100
o := MemGetStats()
GuiControl,, Mem, %memLabel%%o%
Return
TopProcess:
SetTimer TopProcess, Off
ControlGet tplist, List, ,SysListView321, ahk_pid %PID%
StatusBarGetText nop, 1, ahk_pid %PID%
StatusBarGetText cpu, 2, ahk_pid %PID%
StringReplace nop, nop, Processes:%A_Space%,
StringReplace cpu, cpu, CPU Usage:%A_Space%,
GuiControl,,nops, %nop% ; Update no. of processes.
GuiControl,,cpu, %cpu% ; Update cpu usage.
Loop Parse, tplist, `n
{
l := A_LoopField
IfInString l, System Idle Process, Continue
Break
}
StringSplit d, l, %A_Tab%
StringTrimRight d1, d1, 4 ; Remove .exe extention.
If d2 < 01 ; No cpu activity.
{
tp=
GuiControl,,topp ; Clear top process field.
}
Else {
tp = %d1%
GuiControl,,topp, %tp% ; Update top process.
}
d2=
SetTimer TopProcess, On
Return
NetMeter:
SetTimer, NetMeter, Off
DllCall("iphlpapi\GetIfEntry", "Uint", ptr)
dnNew := DecodeInteger(ptr + 552) , upNew := DecodeInteger(ptr + 576)
dnRate := Round((dnNew - dnOld) ) , upRate := Round((upNew - upOld) )
PollMs := (dnRate - upRate = 0) ? 1024 : 256
IfGreater,dnRate,0, IfGreater,upRate,0, SetEnv,iNo,60 ; Recv/Sent
IfGreater,dnRate,0, IfEqual ,upRate,0, SetEnv,iNo,61 ; Recv
IfEqual ,dnRate,0, IfGreater,upRate,0, SetEnv,iNo,62 ; Sent
IfEqual ,dnRate,0, IfEqual ,upRate,0, SetEnv,iNo,63 ; None
Menu, Tray, Icon, NetShell.dll, % iNo
GuiControl,, netIcon, *Icon%iNo% NetShell.dll
GuiControl,, Sent, % Round((((upNew) /1024)/1024),2) . " MB"
GuiControl,, Recv, % Round((((dnNew) /1024)/1024),2) . " MB"
GuiControl,, kbps, % Round((dnrate+uprate)/PollMs) . " KB/s"
GuiControl,, band, % Round((((upNew+dnNew) /1024)/1024),2) . " MB"
prv_iNo := iNo , dnOld := dnNew , upOld := upNew
SetTimer, NetMeter, %PollMs%
Return
UpdateDrives:
Loop Parse, driveList
{
dl := A_LoopField
Letter = %A_LoopField%:\
DriveGet Cap_%dl%, Cap, %Letter%
Cap := number(Cap_%dl%)
DriveSpaceFree Free_Space, %Letter% ;Get the free space in each drive
Free_Space := number(Free_Space)
DriveGet, label_%dl%, label, %Letter%
StringUpper label, label_%dl%, T
GuiControl,, Free_%dl%, %Free_Space%
}
Return
StartTM:
; Save users preferred columns in TM, to be restored on exit.
RegRead OrigReg, HKEY_CURRENT_USER, Software\Microsoft\Windows NT\CurrentVersion\TaskManager, Preferences
; Registry value for the two needed columns.
2c=9C020000E803000002000000010000000100000045010000B0000000D9020000800200000100000000000000020000000300000004000000FFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007800740051006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000010000000200000003000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF010000000000000000000000010000000000000001000000000000000000000004000000FFFFFFFF040000000400000004000000040000000400000004000000040000000400000004000000040000000400000004000000040000000400000004000000040000000400000004000000040000000400000004000000040000000400000078000000260000002600000026000000260000002600000026000000260000002600000026000000260000002600000026000000260000002600000026000000260000002600000026000000260000002600000026000000260000002600000026000000260000000000000001000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47000000000000000000000001000000
RegWrite REG_BINARY, HKEY_CURRENT_USER, Software\Microsoft\Windows NT\CurrentVersion\TaskManager, Preferences, %2c%
Run taskmgr.exe,,, PID ; Run Task Manager.
WinWait ahk_pid %PID%
Control TabLeft,9, SysTabControl321, ahk_pid %PID%
Control TabRight,1,SysTabControl321, ahk_pid %PID% ; Select processes tab.
ControlClick x170 y96, ahk_pid %PID%,,, 2 ; Sort by cpu usage.
Return
WatchTM:
IfWinExist ahk_pid %PID%
Return
SetTimer WatchTM, Off
MsgBox 0,SysMon,You have closed Task Manager!.`nSysMon needs Task Manager to be running. Once it restarts use the tray menu to hide it.`n`nTask Manager will now restart.
RegWrite REG_BINARY, HKEY_CURRENT_USER, Software\Microsoft\Windows NT\CurrentVersion\TaskManager, Preferences, %OrigReg% ; Restore original column settings.
GoSub StartTm
SetTimer WatchTM, On
Return
TraySetup:
Menu Tray, Icon, NetShell.dll, 63
Menu Tray, Tip, SysMon
Menu Tray, NoStandard
Menu Options, Add, &Memory, TrayEvent
Menu Options, Add, &CPU/Process, TrayEvent
Menu Options, Add, &Network, TrayEvent
Menu Options, Add, Drive &R/W, TrayEvent
Menu Options, Add, Drive &Space, TrayEvent
Menu Options, Add, &All Monitoring, TrayEvent
Menu Tray, Add, &Pause Monitoring, :Options
Menu Tray, Add
Menu AutoHotkey, Standard
Menu Tray, Add, &AutoHotkey, :AutoHotkey
Menu Tray, Add
Menu Tray, Add, Show &Task Manager, TrayEvent
Menu Tray, Add, &Always On Top, TrayEvent
Menu Tray, Add, &Default Placement, TrayEvent
Menu Tray, Default, &Always On Top
Return
TrayEvent:
If (!TrayEvent)
TrayEvent = %A_ThisMenuItem%
If (TrayEvent = "Show &Task Manager") {
teShowTM := !teShowTM
If (teShowTM) {
Menu Tray, ToggleCheck, Show &Task Manager ; Show.
WinShow ahk_pid %PID%
SetTimer TopProcess, Off
GuiControl,,topp
GuiControl,,cpu
GuiControl,,nops
SetTimer WatchTM, 100
}
Else {
Menu Tray, ToggleCheck, Show &Task Manager ; Hide
SetTimer WatchTM, Off
WinHide ahk_pid %PID%
SetTimer TopProcess, On
}
}
If (TrayEvent = "&Always On Top") {
teAOT := !teAOT
If (teAOT) {
Menu Tray, ToggleCheck, &Always On Top ; Un-pinned, always on top.
Set_Parent_by_class("","")
Gui +AlwaysOnTop
}
Else {
Menu Tray, ToggleCheck, &Always On Top ; Pin to desktop.
Set_Parent_by_class("Progman","")
}
}
If (TrayEvent = "&Default Placement")
Gui Show,NoActivate x%GuiXPos% y%GuiYPos%,SysMon
If (TrayEvent = "&Memory") {
teMemory := !teMemory
If (teMemory) {
SetTimer UpdateMem, Off
Menu Options, ToggleCheck, &Memory
}
Else {
SetTimer UpdateMem, On
Menu Options, ToggleCheck, &Memory
}
}
If (TrayEvent = "&CPU/Process") {
teCPU := !teCPU
If (teCPU) {
SetTimer TopProcess, Off
GuiControl,,topp, Paused
GuiControl,,cpu, --
GuiControl,,nops, --
Menu Options, ToggleCheck, &CPU/Process
}
Else {
SetTimer TopProcess, On
Menu Options, ToggleCheck, &CPU/Process
}
}
If (TrayEvent = "&Network") {
teNetwork := !teNetwork
If (teNetwork) {
SetTimer NetMeter, Off
Menu Options, ToggleCheck, &Network
}
Else {
SetTimer NetMeter, On
Menu Options, ToggleCheck, &Network
}
}
If (TrayEvent = "Drive &R/W") {
teDriveRW := !teDriveRW
If (teDriveRW) {
SetTimer ScanDrv, Off
Menu Options, ToggleCheck, Drive &R/W
}
Else {
SetTimer ScanDrv, On
Menu Options, ToggleCheck, Drive &R/W
}
}
If (TrayEvent = "Drive &Space") {
teDriveSpace := !teDriveSpace
If (teDriveSpace) {
SetTimer UpdateDrives, Off
Menu Options, ToggleCheck, Drive &Space
}
Else {
SetTimer UpdateDrives, On
Menu Options, ToggleCheck, Drive &Space
}
}
If (TrayEvent = "&All Monitoring") {
tePauseAll := !tePauseAll
If (tePauseAll) {
Menu Options, ToggleCheck, &All Monitoring
Pause
}
Else {
Menu Options, ToggleCheck, &All Monitoring
Pause
}
}
TrayEvent=
Return
uiMove:
PostMessage, 0xA1, 2,,, A
Return
Out:
WinClose ahk_pid %PID% ; Quit Task Manager.
RegWrite REG_BINARY, HKEY_CURRENT_USER, Software\Microsoft\Windows NT\CurrentVersion\TaskManager, Preferences, %OrigReg% ; Restore original column settings.
ExitApp
Return
GuiClose:
GuiEscape:
ExitApp
Return
; Functions.
MemGetStats() {
global
output =
VarSetCapacity(memorystatus, 4+4+4+4+4+4+4+4)
success := DllCall("kernel32.dll\GlobalMemoryStatus", "uint", &memorystatus)
total := Round(ReadInteger(&memorystatus,8,4, false)/1024/1024)
used := total - Round(ReadInteger(&memorystatus,12,4, false)/1024/1024)
output := output round(mem) "% - ( " used " of " total " MB )"
return output
}
ReadInteger( p_address, p_offset, p_size, p_hex=true ) {
value = 0
old_FormatInteger := a_FormatInteger
if ( p_hex )
SetFormat, integer, hex
else
SetFormat, integer, dec
loop, %p_size%
value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8* ( a_Index-1 ) ) )
SetFormat, integer, %old_FormatInteger%
return, value
}
number(n) {
StringSplit, n, n, .
If (d := Mod(l := StrLen(Abs(n1)), 3)) and l > 3
n1 := RegExReplace(n1, "(\d{" . d . "})", "$1,", "", 1)
Return, RegExReplace(n1, "(\d{3})(?!$)", "$1,") . (n2 != "" ? "." . n2 : "")
}
DecodeInteger(ptr) {
Return *ptr | *++ptr << 8 | *++ptr << 16 | *++ptr << 24
}
GetIfTable(ByRef tb, bOrder = False) {
nSize := 4 + 860 * GetNumberOfInterfaces() + 8
VarSetCapacity(tb, nSize)
Return DllCall("iphlpapi\GetIfTable", "Uint", &tb, "UintP", nSize, "int", bOrder)
}
GetIfEntry(ByRef tb, idx) {
VarSetCapacity(tb, 860)
DllCall("ntdll\RtlFillMemoryUlong", "Uint", &tb + 512, "Uint", 4, "Uint", idx)
Return DllCall("iphlpapi\GetIfEntry", "Uint", &tb)
}
GetNumberOfInterfaces() {
DllCall("iphlpapi\GetNumberOfInterfaces", "UintP", nIf)
Return nIf
}
Set_Parent_by_class(Window_Class, Gui_Number) ; class e.g. Shell_TrayWnd, gui number is e.g. 99
{
Parent_Handle := DllCall( "FindWindowEx", "uint",0, "uint",0, "str", Window_Class, "uint",0)
Gui +LastFound ;%Gui_Number%:
Return DllCall( "SetParent", "uint", WinExist(), "uint", Parent_Handle )
}