Jump to content

Process Watcher


arsi
 Share

Recommended Posts

Hi,

I made this little program with autoit. Now it works great on windows xp, but on windows 2k, it seems to at times hang (the execution of the program wont end when all the monitored processes have ended).

Any clues why it won't always work on windows 2000?

The purpose of the program is to monitor processes named in the ini file like:

processwatcher.ini:

[Common]
ProcessName1=notepad.exe
ProcessName2=calc.exe
TitleText=Processes are being monitored please wait...
AbortHotKey={NUMPADADD}
ProcessWaitTimeout=-1
WindowWidth=500
WindowHeight=200
WindowX=0
WindowY=0
LastCmd1=explorer.exe
LastCmd1Wait=

As you can see from above, you can define monitored process to contain multiple processes by defining them by adding +1 to the index of processname. Like shown above. If you wish to monitor only one process, then write only ProcessName1=<name of the process>. TitleText holds the text to be shown in top of the window. AbortHotkey is a hotkey which aborts the process monitoring, and launches sequentially LastCmds defined also above. ProcessWaitTimeout is a safety switch, so processes are not waited for all iternity, if this key holds value <> -1. WindowWidth and WindowHeight hold the dialog's dimension info, and WindowX and WindowY hold the coordinate info for it. LastCmd and LastCmdWait arrays can contain multiple commands to be executed sequentially, you can add more than one command to be executed by first making LastCmd1 and then LastCmd2... Remember to add also LastCmd1Wait, and LastCmd2Wait to match LastCmd arrays dimension.

Notice the dialog will NOT show up, before all the processes to be monitored are running

Thats basically it, here is the script:

processwatcher.au3:

#Include <date.au3>
#include <GUIConstants.au3>
#include <Array.au3>

Dim $Terminate = 0
Dim $ExecTime = 0
Dim $Inited = 0
Dim $iHours = 0
Dim $iMins = 0
Dim $iSecs = 0
Dim $StartTicks = 0
Dim $EndTicks = 0
Dim $Difference = 0
Dim $Done = 0
Dim $ProcessName = ""
Dim $AbortHotKey = "{ESC}"
Dim $TitleText = ""
Dim $ProcessWaitTimeout = 10; In minutes
Dim $default_titleprefix = "Waiting for "
Dim $default_titlesuffix = " to complete. Please wait."
dim $default_lastcmdwait = 1
Dim $WindowWidth
Dim $WindowHeight
Dim $WindowX
Dim $WindowY
Dim $default_width = 500
Dim $default_height = 130
Dim $default_x = 0
Dim $default_y = 0
Dim $IniFile

Dim $ProcessNamesArr
Dim $ProcessesStatesArr
Dim $ProcessCountArr
Dim $LastCmdArr
Dim $LastCmdWaitArr

If $CmdLine[0] > 0 Then
    $IniFile = $CmdLine[1]
Else
    $IniFile = "processwatcher.ini"
EndIf

If FileExists(@ScriptDir & "\" & $IniFile) = 0 Then
    MsgBox(0,"Error opening the ini file", "Cannot open the file: '" & @ScriptDir & "\" & $IniFile & "'")
    Exit(0)
EndIf

ReadIni()

Func ReadIni()
    Dim $var

    $ProcessNamesArr = _ArrayCreate("")
    $ProcessesStatesArr = _ArrayCreate("")
    $ProcessCountArr = _ArrayCreate("")
    $LastCmdArr = _ArrayCreate("")
    $LastCmdWaitArr = _ArrayCreate("")
    Dim $itemi
    $itemi = 1

    While 1
        $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "ProcessName" & $itemi, "NotFound")
        If $var <> "NotFound" Then
            _ArrayAdd($ProcessNamesArr, $var)
            _ArrayAdd($ProcessesStatesArr, 0)
            _ArrayAdd($ProcessCountArr, 0)
        Else
            if $itemi = 1 Then
                MsgBox(16,"Error...","Cannot read from processwatcher.ini file the process name to be monitored!")
                Exit(0)
            EndIf
            ExitLoop
        EndIf
        
        $itemi = $itemi + 1
    WEnd

    $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "AbortHotKey" , "NotFound")
    If $var <> "NotFound" Then
        $AbortHotKey = $var
    Else
        MsgBox(16,"Error...","Cannot read from processwatcher.ini file the Abort Hotkey setting!")
        Exit(0)
    EndIf
    
    $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "TitleText" , "NotFound")
    If $var <> "NotFound" Then
        $TitleText = $var
    EndIf
    
    $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "ProcessWaitTimeout" , "NotFound")
    If $var <> "NotFound" Then
        $ProcessWaitTimeout = $var
    EndIf

    $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "WindowWidth" , "NotFound")
    If $var <> "NotFound" Then
        $WindowWidth = $var
    Else
        $WindowWidth = $default_width
    EndIf

    $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "WindowHeight" , "NotFound")
    If $var <> "NotFound" Then
        $WindowHeight = $var
    Else
        $WindowHeight = $default_height
    EndIf

    $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "WindowX" , "NotFound")
    If $var <> "NotFound" Then
        $WindowX = $var
    Else
        $WindowX = $default_x
    EndIf

    $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "WindowY" , "NotFound")
    If $var <> "NotFound" Then
        $WindowY = $var
    Else
        $WindowY = $default_y
    EndIf

    $itemi = 1
    While 1
        $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "LastCmd" & $itemi, "NotFound")
        If $var <> "NotFound" Then
            _ArrayAdd($LastCmdArr, $var)
        Else
            ExitLoop
        EndIf
        
        $var = IniRead(@ScriptDir & "\" & $IniFile, "Common", "LastCmd" & $itemi & "Wait", "NotFound")
        If $var <> "NotFound" Then
            _ArrayAdd($LastCmdWaitArr, $var)
        Else
            _ArrayAdd($LastCmdWaitArr, $default_lastcmdwait)
        EndIf

        $itemi = $itemi + 1
    WEnd
EndFunc

; Create GUI
If $TitleText <> "" Then
    GUICreate($TitleText,$WindowWidth,$WindowHeight,$WindowX,$WindowY,0,$WS_EX_TOOLWINDOW & $WS_EX_TOPMOST)
Else
    GUICreate($default_titleprefix & $ProcessName & $default_titlesuffix,$WindowWidth,$WindowHeight,$WindowX,$WindowY,0,$WS_EX_TOOLWINDOW & $WS_EX_TOPMOST)
EndIf
$progressbar1 = GUICtrlCreateProgress (10,10,$WindowWidth-30,20)
GUICtrlSetColor(-1,32250); not working with Windows XP Style
$progressbar2 = GUICtrlCreateProgress (10,40,$WindowWidth-30,20,$PBS_SMOOTH)
$lb_Time = GuiCtrlCreateLabel('', 10, 70, $WindowWidth-30, 20, $SS_CENTER)

If Ubound($ProcessNamesArr) > 2 Then
    $lb_listInfo = GuiCtrlCreateLabel('These processes are being watched:', 10, 90, $WindowWidth-30, 20, $SS_CENTER)
    $mylist=GUICtrlCreateList ('', 10,110,$WindowWidth-30, 60,$WS_VSCROLL)
    GUICtrlSetLimit(-1,200); to limit horizontal scrolling
    Dim $Temp
    For $I = 1 to UBound($ProcessNamesArr)-1
        If $I = 1 Then
            $Temp = $ProcessNamesArr[$I]
        Else
            $Temp = $Temp & "|" & $ProcessNamesArr[$I]
        EndIf
    Next
    GUICtrlSetData($mylist,$Temp)
EndIf

GUISetState (@SW_HIDE)

HotKeySet($AbortHotKey, "Terminate")

$wait = 60; wait 20ms for next progressstep
$s = 0; progressbar-saveposition
$Ticks = _TimeToTicks(@HOUR,@MIN,@SEC)
Dim $ArrayCntr
Dim $ArrayCntr2

; Install initial status array of running process to be monitored
For $ArrayCntr = 1 to UBound($ProcessNamesArr) -1
    $ProcessCountArr[$ArrayCntr] = ChkAmountOfProcessX($ProcessNamesArr[$ArrayCntr])
Next

do
    $msg = GUIGetMsg()
    For $i = $s To 100
        $m = GUIGetMsg()
        If $m = -3 Then Exit(0)
        
        $s=0
        GUICtrlSetData($progressbar1,$i)
        GUICtrlSetData($progressbar2,(100 - $i))
        Sleep($wait)

        If $Terminate = 1 Then 
            $Done=1
            ExitLoop
        EndIf

        $ETicks = _TimeToTicks(@HOUR,@MIN,@SEC)
        $Diff = $ETicks - $Ticks
        _TicksToTime($Diff,$iHours,$iMins,$iSecs)
        If $ProcessWaitTimeout <> -1 Then
            If ($iMins > $ProcessWaitTimeout And $Inited = 0) Then
                MsgBox(0,"Error...","No process found in set time. Aborting")
                Exit(0)
            EndIf
        EndIf

        For $ArrayCntr = 1 to UBound($ProcessNamesArr) -1
            If $ProcessesStatesArr[$ArrayCntr] <= 2 Then
                $ProcessCount = ChkAmountOfProcessX($ProcessNamesArr[$ArrayCntr])
                if $ProcessCount <= $ProcessCountArr[$ArrayCntr] And $ProcessesStatesArr[$ArrayCntr] = 1 Then
                    $ProcessesStatesArr[$ArrayCntr] = 2;The process to be monitored has been terminated or its instance counter be decreased to the value when processwatcher was launched
                ElseIf $ProcessCount > $ProcessCountArr[$ArrayCntr] And $ProcessesStatesArr[$ArrayCntr] = 0 Then
                    $ProcessesStatesArr[$ArrayCntr] = 1;The process has been started, but it hasnt yet been finished

                    if $Inited = 0 Then
                        $StartTicks = _TimeToTicks(@HOUR,@MIN,@SEC)
                        $Inited = 1
                        GUISetState (@SW_SHOW)
                    EndIf

                    $EndTicks = _TimeToTicks(@HOUR,@MIN,@SEC)
                    $Difference = $EndTicks - $StartTicks
                    _TicksToTime($Difference, $iHours, $iMins, $iSecs)
                    If $iHours < 0 Or $iMins < 0 Or $iSecs < 0 Then
                        GUICtrlSetData($lb_Time,"Time run: Over 24:00:00")
                    Else
                        GUICtrlSetData($lb_Time,"Time run: " & $iHours & ":" & $iMins & ":" & $iSecs)
                    endif 
                EndIf
            EndIf
        Next

        $AllDone = 1
        If $Inited = 1 Then
            For $ArrayCntr2 = 1 to Ubound($ProcessesStatesArr) -1
                if $ProcessesStatesArr[$ArrayCntr2] <> 2 Then
                    $AllDone = 0

                    $EndTicks = _TimeToTicks(@HOUR,@MIN,@SEC)
                    $Difference = $EndTicks - $StartTicks
                    _TicksToTime($Difference, $iHours, $iMins, $iSecs)
                    If $iHours < 0 Or $iMins < 0 Or $iSecs < 0 Then
                        GUICtrlSetData($lb_Time,"Time run: Over 24:00:00")
                    Else
                        GUICtrlSetData($lb_Time,"Time run: " & $iHours & ":" & $iMins & ":" & $iSecs)
                    endif 
                    ExitLoop
                EndIf
            Next
            If $AllDone = 1 Then
                $Done = 1
            EndIf
        EndIf
    Next

    if $i > 100 then
       $s = 0
    endif
until ($msg = $GUI_EVENT_CLOSE Or $Done = 1)

If $Done = 1 Then
    Sleep(2000)
    GUISetState (@SW_HIDE)

   ; Create GUI
    If $TitleText <> "" Then
        GUICreate($TitleText,$WindowWidth,$WindowHeight,$WindowX,$WindowY,0,$WS_EX_TOOLWINDOW & $WS_EX_TOPMOST)
    Else
        GUICreate($default_titleprefix & $ProcessName & $default_titlesuffix,$WindowWidth,$WindowHeight,$WindowX,$WindowY,0,$WS_EX_TOOLWINDOW & $WS_EX_TOPMOST)
    EndIf
    $lb_Time = GuiCtrlCreateLabel('', 10, 50, $WindowWidth-30, 80, $SS_CENTER)
    GUISetState (@SW_SHOW)

    for $Cntr = 1 to UBound($LastCmdArr) - 1
        if $LastCmdArr[$Cntr] <> "" Then
            if $LastCmdWaitArr[$Cntr] <> "" Then
                GUICtrlSetData($lb_Time,"Running command " & $Cntr & "/" & UBound($LastCmdArr)-1 & ":" & @CR & @LF & "'" & $LastCmdArr[$Cntr] & "'" & @CR & @LF & "Please wait it to end.")
                    $Pid = Run($LastCmdArr[$Cntr], @SCRIPTDIR)   ;RunWait sometimes doesn't work - this must be used instead on such cases
                    ProcessWaitClose($Pid)
            Else
                GUICtrlSetData($lb_Time,"Running command " & $Cntr & "/" & UBound($LastCmdArr)-1 & ":" & @CR & @LF & "'" & $LastCmdArr[$Cntr] & "'" & @CR & @LF & "Please wait...")
                Run($LastCmdArr[$Cntr],@SCRIPTDIR,@SW_SHOWNORMAL)
            EndIf
        EndIf
    next
EndIf

Func Terminate()
    $Terminate = 1
EndFunc

Func ChkAmountOfProcessX($ProcessName)

    $amount = 0
    
    $list = ProcessList($ProcessName)
    for $i = 1 to $list[0][0]
        $amount = $amount + 1
    Next
    
    Return $amount
EndFunc
Edited by arsi
Link to comment
Share on other sites

You could try and add:

Opt('TrayIconDebug', 1)

Run the script on the 2k machine and watch what it does.

It could be the item that you are using Run() or previously RunWait(). Not the script itself? The syntax of cmd in 2k has changed in XP if that is what you are executing.

Most members ask for support in the support forum. Next time...please.

Link to comment
Share on other sites

You could try and add:

Opt('TrayIconDebug', 1)

Run the script on the 2k machine and watch what it does.

It could be the item that you are using Run() or previously RunWait(). Not the script itself? The syntax of cmd in 2k has changed in XP if that is what you are executing.

Most members ask for support in the support forum. Next time...please.

Txs, will try that Option out ;)
Link to comment
Share on other sites

Maybe, this is a great thing to work like a watchdog for viruscanners and/or firewalls.

With little modifications it will do the job, 'cause nobody knows the name of the script. ;)

Not tested but a good idea...

Westi

Link to comment
Share on other sites

Maybe, this is a great thing to work like a watchdog for viruscanners and/or firewalls.

With little modifications it will do the job, 'cause nobody knows the name of the script. ;)

Not tested but a good idea...

Westi

Txs mate. I work for a living in a company where we make among other things automated installation packages. This was needed, so I created it from scrath. As I love autoit :P thou these process related functions and their functionality working in windows 2000 made me bit worry, as the script doesn't seem to always work.. or its just me.

Anyway I wanted to post this for you guys, to study and perhaps give feedback of it - what you would have done otherwise. And post the modified version of it here. I haven't copyrighted the code, so feel free use it, but give credit to the original author of the script, if you attend to use it - thats all.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...