;--------------------------------------------------------------------------------------------------------------- ; CHANGELOG: ; ; Dec 16 2021: Initial release by Glisense ltd ; ; Current script is designed for use together with Keyboard Extension® (https://keyboardextension.com) ; ; For the latest version, description and licensing terms go to https://keyboardextension.com/plugins/06c3ba7c ; ;--------------------------------------------------------------------------------------------------------------- #NoTrayIcon ; Hide tray icon #Persistent ; Keep the script permanently running until it gets terminated CoordMode, ToolTip global sLabels, sValues, sFullLoad ; Array of Logical processors labels, Array of Logical processors loads, Total load on all logical processors GetCoresLoad() SetTimer, TrackCoresLoad, 1000 Return TrackCoresLoad() { CPU_Info := GetCoresLoad() names := [], values := [], fullLoad := 0 for k, v in CPU_Info { names.Push({ id: A_Index, value: k }) values.Push({ id: A_Index, value: Round(v) . "%" }) fullLoad += v } sLabels := AhkToJSON(names) sValues := AhkToJSON(values) sFullLoad := Round( fullLoad/CPU_Info.Count() ) . "%" ; ToolTip, % sLabels . "`n" . sValues . "`n" . fullLoad, 3, 3, 1 } GetCoresLoad() { static hModule := DllCall("LoadLibrary", "Str", "ntdll.dll", "Ptr"), LI := {} , SYSTEM_INFORMATION_CLASS := 0x8 ; SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION size := VarSetCapacity(buf, 0, 0) DllCall("ntdll\NtQuerySystemInformation", "Int", SYSTEM_INFORMATION_CLASS, "Ptr", &buf, "UInt", 0, "UInt*", size) size := VarSetCapacity(buf, size, 0) if DllCall("ntdll\NtQuerySystemInformation", "Int", SYSTEM_INFORMATION_CLASS, "Ptr", &buf, "UInt", size, "UInt*", 0) != 0 Return ErrorLevel CI := {}, Offset := 0, CPU_COUNT := size//48, CPU_USAGE := new CaseSenseList loop % CPU_COUNT { i := A_Index CI[i, "IT"] := NumGet(buf, Offset + 0, "UInt64") ; IdleTime CI[i, "KT"] := NumGet(buf, Offset + 8, "UInt64") ; KernelTime CI[i, "UT"] := NumGet(buf, Offset + 16, "UInt64") ; UserTime CPU_USAGE["Thread " . i] := Round(100 - ( CI[i, "IT"] - LI[i, "IT"] )/( CI[i, "KT"] - LI[i, "KT"] + CI[i, "UT"] - LI[i, "UT"] )*100) . "%" Offset += 48 } LI := CI Return CPU_USAGE } class CaseSenseList { __New() { ObjRawSet(this, "_list_", []) } __Delete() { this.SetCapacity("_list_", 0) ObjRawSet(this, "_list_", "") } __Set(key, value) { for k, v in this._list_ { if !(v[1] == key) continue v[2] := value keyExist := true } until keyExist if !keyExist this._list_.Push([key, value]) Return value } __Get(key) { if (key == "_list_") Return for k, v in this._list_ { if (v[1] == key) Return v[2] } } _NewEnum() { Return new this._CustomEnum_(this._list_) } class _CustomEnum_ { __New(list) { this.i := 0 this.list := list } Next(ByRef k, ByRef v := "") { if ++this.i <= this.list.Length() { k := this.list[this.i, 1] v := this.list[this.i, 2] Return true } } } Count() { Return this._list_.Length() } Delete(key) { for k, v in this._list_ continue until v[1] == key && keyExist := true Return keyExist ? this._list_.RemoveAt(k)[2] : "" } HasKey(key) { for k, v in this._list_ if (v[1] == key) Return true Return false } } AhkToJSON(obj, indent := "") { static Doc, JS if !Doc { Doc := ComObjCreate("htmlfile") Doc.write("") JS := Doc.parentWindow ( Doc.documentMode < 9 && JS.execScript() ) } if indent|1 { if IsObject( obj ) { isArray := true for key in obj { if IsObject(key) throw Exception("Invalid key") if !( key = A_Index || isArray := false ) break } for k, v in obj str .= ( A_Index = 1 ? "" : "," ) . ( isArray ? "" : %A_ThisFunc%(k, true) . ":" ) . %A_ThisFunc%(v, true) Return isArray ? "[" str "]" : "{" str "}" } else if !(obj*1 = "" || RegExMatch(obj, "^-?0(?=[^.])|\s")) Return obj for k, v in [["\", "\\"], [A_Tab, "\t"], ["""", "\"""], ["/", "\/"], ["`n", "\n"], ["`r", "\r"], [Chr(12), "\f"], [Chr(8), "\b"]] obj := StrReplace( obj, v[1], v[2] ) Return """" obj """" } sObj := %A_ThisFunc%(obj, true) Return JS.eval("JSON.stringify(" . sObj . ",'','" . indent . "')") }