AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to detect "Top Process"

 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
*MsgBox
Guest





PostPosted: Thu Apr 19, 2007 10:39 pm    Post subject: How to detect "Top Process" Reply with quote

Is it possible to detect the "top process" using AutoHotkey?

By "top process" I mean, the running process that is using the most CPU time at any moment.

The only things that I have found that (sort of) work are a vbscript that outputs to a txt file and the Task Managers "CPU" column. Neither are what I am looking for as the vbscript takes too long to complete and TM has to be running continually.

I am writing a script to replace "CoolMon" a system monitoring app and top process is the one thing I can't give up, its too useful!!.

Below is the vbscript. I have edited it from the original version so that it just outputs the process name. To be honest though, I haven't got a clue what I'm looking at...I don't know vb al all. Smile
I am hoping that maybe there is something in the script that AutoHotkey can use, possibly DllCall?? (something else that I haven't a clue about!)

Any help and guidance with this will be very much appreciated.

Thanks.
Code:
'*****  To make it easy, keep both sleep.vbs and THIS script in the same folder.

DIM First(1000,3)      'keeps track of the 1st snapshot info
DIM Second(1000,3)   'keeps track of the 2nd snapshot info

Directory = ""
Sleep = "sleep.vbs"
oPath = " "
oFile = "Processes.txt"
TheDate = Date
TheTime = Time

Set fs = CreateObject("Scripting.FileSystemObject")
Set colItems = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf ("Win32_Process")
Set outFile = fs.CreateTextFile(oPath & oFile, True)

For Each objProcess in GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2").ExecQuery("SELECT * FROM Win32_Process")
   x=x+1
   First(x,0) = timer         'current time
   First(x,1) = objProcess.Name   'process name
   First(x,2) = (CSng(objProcess.KernelModeTime) + CSng(objProcess.UserModeTime)) / 10000000   'how many seconds the process has used since it first started
Next

'CreateObject("WScript.Shell").Run Directory & Sleep,1,True

For Each objProcess in GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2").ExecQuery("SELECT * FROM Win32_Process")
   y=y+1
   Second(y,0) = timer
   Second(y,1) = objProcess.Name
   Second(y,2) = (CSng(objProcess.KernelModeTime) + CSng(objProcess.UserModeTime)) / 10000000
Next

For z = 1 to y
   ProcessTime = round(((Second(z,2)-First(z,2)) / (Second(z,0)-First(z,0))) * 100)   'calculates to see if there's been an increase in process activity
   If ProcessTime then
     TotalProcessTime = TotalProcessTime + ProcessTime   
'-----The following processes are excluded from being the top process. You can add/remove whatever you want.
   If Second(z,1) <> "System Idle Process" then
       If ProcessTime > TopProcessTime then
          TopProcessTime = ProcessTime
           reduce = InStr(Second(z,1), ".") - 1
         If reduce > 0 then
          TopProcessName = Left(Second(z,1),reduce)   'removes the extension (.xxx)
        Else
                     TopProcessName = Second(z,1)
        End If
      End If
   End If
   End If
Next

If TopProcessTime > 100 then TopProcessTime = 100   
FindTheTopProcess = TopProcessName & " - " & TopProcessTime & "%" : If FindTheTopProcess = " - %" then FindTheTopProcess = ""
If TopProcessName = "" then FindTheTopProcess = " "
TopProcess = FindTheTopProcess
if TopProcessTime < 50 then FindTheTopProcess = ""

Outfile.Write "" & TopProcessName & ""

outfile.close
Back to top
BoBo
Guest





PostPosted: Fri Apr 20, 2007 8:03 am    Post subject: Reply with quote

Quote:
I am hoping that maybe there is something in the script that AutoHotkey can use, possibly DllCall??
Good chance. If not, I think you should check out Sysinternals PSList tool meanwhile.
Back to top
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Fri Apr 20, 2007 8:24 am    Post subject: Reply with quote

You may use this script after adjusting it to your need:
http://www.autohotkey.com/forum/viewtopic.php?t=16632

replacing Query with
Code:
Query := "SELECT Caption, KernelModeTime, UserModeTime FROM " . Class
Back to top
View user's profile Send private message
*MsgBox
Guest





PostPosted: Sun Apr 22, 2007 1:07 am    Post subject: Reply with quote

Thanks both of you. Cool

I will have a go at making something out of what you have given me....
Back to top
MsgBox



Joined: 17 Nov 2005
Posts: 181
Location: Leicester, UK

PostPosted: Sun Apr 22, 2007 6:50 pm    Post subject: Reply with quote

Well I'm not having too much luck here. Sad

I can get the top process with Seans script but...the script itself is using a lot of cpu time and as it is supposed to be working "quietly" in the background it sort of defeats the object etc....sigh!

Code:
#NoEnv
#Persistent
#Include CoHelper.ahk

Namespace := "root\cimv2"
Class := "Win32_Process"

QLang := "WQL"
Query := "SELECT Caption, KernelModeTime, UserModeTime FROM " . Class

Ansi2Unicode(Namespace, wNamespace)
Ansi2Unicode(QLang, wQLang)
Ansi2Unicode(Query, wQuery)

CoInitialize()

GUID4String(CLSID_SWbemLocator, "{76A64158-CB41-11D1-8B02-00600806D9B6}")
GUID4String( IID_ISWbemLocator, "{76A6415B-CB41-11D1-8B02-00600806D9B6}")

ploc := CreateObject(CLSID_SWbemLocator, IID_ISWbemLocator)

DllCall(VTable(ploc, 7), "Uint", ploc, "Uint", 0, "str", wNamespace
   , "Uint", 0, "Uint", 0, "Uint", 0, "Uint", 0, "int",  0, "Uint", 0, "UintP", psvc)


SetTimer TP, 50

TP:
SetTimer TP, Off
GoSub GetData ; Get first snapshot.
Sleep 10
GoSub GetData ; Get second snapshot.
Snap = %sn1%
lp = 1
GoSub Process ; Build first ss list.
Snap = %sn2%
lp = 2
GoSub Process ; Compare lists
Sort c, NR    ; Bring highest cpu user to top.
ToolTip % c "Processes: " cnt
;MsgBox % c "Processes: " cnt
lp=
sn1=
sn2=
snap1=
ttl=
c=
SetTimer TP, On
Return

DllCall(VTable(penm, 2), "Unit", penm)
DllCall(VTable(pset, 2), "Unit", pset)
DllCall(VTable(psvc, 2), "Unit", psvc)
DllCall(VTable(ploc, 2), "Unit", ploc)

CoUninitialize()



Process:
StringReplace Snap, Snap, `ninstance of Win32_Process`n{,|,A
StringReplace Snap, Snap, %A_Tab%,, A
StringReplace Snap, Snap, },,A
StringReplace Snap, Snap, `;,, A

Loop Parse, Snap, |, "
{
   line := A_LoopField
   IfEqual line,, Continue
   Loop Parse, line, `n, "
   {
      l := A_LoopField
      IfInString l, Caption
      {
         StringGetPos pos, l, "
         StringTrimLeft n, l, % pos+1
         Continue
         }
      IfInString l, Handle
      {
         StringGetPos pos, l, "
         StringTrimLeft h, l, % pos+1
         Continue
         }
      IfInString l, KernelModeTime
      {
         StringGetPos pos, l, "
         StringTrimLeft k, l, % pos+1
         Continue
         }
      IfInString l, UserModeTime
      {
         StringGetPos pos, l, "
         StringTrimLeft u, l, % pos+1
         Continue
         }
      }
     
      If lp = 1                        ; First snapshot.
      {
        s1 := (k + u)/10000000         ; Add KernelModeTime and UserModeTime together.
        Snap1 = %Snap1%%n%%h%-%s1%`n   ; Build fist snapshot list.
        Continue
        }
      Else {                           ; Second snapshot.
         Sleep 10
         s2 := (k + u)/10000000
         Loop Parse, Snap1, `n
         {
            l := A_LoopField
            IfInString l, System Idle Process
               Continue
            IfInString l, %n%%h%       ; Find matching process
            {
               StringGetPos pos, l, -
               StringTrimLeft s1, l, % pos+1 ; Get total time from 1st snap.
               If s2 = %s1%                  ; No change.
                  Continue
               ttl := (s2 - s1) ;/10000000   ; Process was active...
               c = %c%%ttl%-%n%`n            ; Build a list.
               Continue
               }
            }
         }
   }

Return

GetData:
   lp++  ; Which loop identifier.
   DllCall(VTable(psvc,15), "Uint", psvc, "str", wQuery, "str", wQLang, "Uint", 0x30, "Uint", 0, "UintP", pset)
   DllCall(VTable(pset, 7), "Uint", pset, "UintP", penm)

   VarSetCapacity(varg, 8 * 2)

   Loop
   {
      cnt := A_Index ; Count number of processes.
      If DllCall(VTable(penm, 3), "Uint", penm, "Uint", 1, "Uint", &varg, "Uint", 0)
      Break

      pobj := DecodeInteger(&varg + 8)
      DllCall(VTable(pobj,22), "Uint", pobj, "Uint", 0, "UintP", pString)
      DllCall(VTable(pobj, 2), "Unit", pobj)
      Unicode2Ansi(pString, sString)
      SysFreeString(pString)

      If lp = 1
      {
         sn1 = %sn1%%sString%`n

         }
      Else {
         sn2 = %sn2%%sString%`n

         }
      }
Return
;Query := "SELECT Caption, KernelModeTime, UserModeTime FROM " . Class


BoBo wrote:
Good chance. If not, I think you should check out Sysinternals PSList tool meanwhile.

psList is a great little tool and the -s switch makes it run in task manager mode showing the top process.
My idea was to redirect the onscreen output to a file then have my script read then delete that file every second. The problem is that the file is locked and cannot be deleted....arrgh!
Is there an easy way to forcibly delete a locked file?

This too used more cpu time but not quite as much as the other script.

Here's a few links on this subject:
http://www.alexfedotov.com/samples/wmitop.asp
http://www.microsoft.com/technet/scriptcenter/resources/qanda/sept05/hey0922.mspx
http://www.codeproject.com/threads/Get_CPU_Usage.asp

I have downloaded a dll that CoolMon uses to get the Top Process, is there any way that that could be used...or is that a stupid question?

Anyway I'm stuck now, any idea's?

Thanks.
Back to top
View user's profile Send private message Visit poster's website
MsgBox



Joined: 17 Nov 2005
Posts: 181
Location: Leicester, UK

PostPosted: Tue Apr 24, 2007 8:16 pm    Post subject: Reply with quote

Here is the best (resource wise) that I have come up with.

Although not ideal, it does the job.

These two examples use Task Manager to get the info.
The first with the default columns and the second with just the "Image Name" and "CPU" columns which doesn't hog the cpu time.
Code:
#Persistent
DetectHiddenWindows On
Run taskmgr.exe,,, PID
WinWait ahk_pid %PID%
Control TabLeft,9, SysTabControl321, ahk_pid %PID%
Control TabRight,1,SysTabControl321, ahk_pid %PID%
ControlClick x270 y100, ahk_pid %PID%,,, 2
WinHide ahk_pid %PID%

SetTimer TopProcess, 50

OnExit Out
Return

TopProcess:
SetTimer TopProcess, Off
ControlGet list, List, ,SysListView321, ahk_pid %PID%
Loop Parse, list, `n
{
   l := A_LoopField
   IfInString l, System Idle Process, Continue
   Loop Parse, l, %A_Tab%
   {
      l1 := A_LoopField
      s = %s%%l1%|
      IfEqual A_Index, 3, Break
      }
   Break
   }
StringSplit d, s, |
StringTrimRight d1, d1, 4
If d3 < 01
   tp=
Else
   tp = %d1% @ %d3%`% CPU

ToolTip % tp
s=
SetTimer TopProcess, On
Return

Out:
WinClose ahk_pid %PID%
ExitApp
Return


Code:
; Unselect "Memory Usage" and "User Name" in Task Manager. (Uses less system resources)
#Persistent
DetectHiddenWindows On
Run taskmgr.exe,,, PID
WinWait ahk_pid %PID%
Control TabLeft,9, SysTabControl321, ahk_pid %PID%
Control TabRight,1,SysTabControl321, ahk_pid %PID%
ControlClick x170 y100, ahk_pid %PID%,,, 2
WinHide ahk_pid %PID%

SetTimer TopProcess, 50

OnExit Out
Return

TopProcess:
SetTimer TopProcess, Off
ControlGet list, List, ,SysListView321, ahk_pid %PID%
Loop Parse, list, `n
{
   l := A_LoopField
   IfInString l, System Idle Process, Continue
   Loop Parse, l, %A_Tab%
   {
      l1 := A_LoopField
      s = %s%%l1%|
      IfEqual A_Index, 2, Break
      }
   Break
   }
StringSplit d, s, |
StringTrimRight d1, d1, 4
If d2 < 01
   tp=
Else
   tp = %d1% @ %d2%`% CPU
ToolTip % tp
s=
SetTimer TopProcess, On
Return

Out:
WinClose ahk_pid %PID%
ExitApp
Return
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group