Sign in to follow this  
Followers 0
jftuga

Proc_Watch script

10 posts in this topic

#1 ·  Posted (edited)

UPDATED: See post #4 for the newest version

I originally wrote this script to lower the priority level of antivirus scanners. If scanning was done while I was using the computer, the system became somewhat unresponsive. I also wrote a .reg file that allows Proc_Watch to run at system startup.

It takes three arguments:

1) Time interval (in seconds) to wait inbetween checking for the processes

2) Priority 0 - 5 (0 lowest, 3 normal, 5 highest)

3,4,5,...) List of process names to check for, if one is found, it's priority will be changed to that of argument #2.

Example:

Proc_Watch 30 0 notepad.exe firefox.exe acrotray.exe

I have posted the code as well as including it as an attachment.

-John

#cs

Proc_Watch
Set priority of a given list of processes to the lowest possible setting
Originally written to help antivirus scanners not hog the cpu
-John Taylor
July-30-2005

Command-line options (all mandatory):
1) time interval in seconds to check for the list of processes
2) priority
3,4,5,...) list of processes to check for

The argument which determines what priority to set
0 - Idle/Low
1 - Below Normal (Not supported on Windows 95/98/ME)
2 - Normal
3 - Above Normal (Not supported on Windows 95/98/ME)
4 - High
5 - Realtime (Use with caution, may make the system unstable)

#ce

#include <GUICONSTANTS.au3>
#notrayicon
Opt ("GUIOnEventMode", 1)
Opt ("MustDeclareVars", 1)
Opt ("RunErrorsFatal", 0 )

Dim $usage = "Command-line options (all mandatory):" & @CR & "1) time interval in seconds to check for the list of processes" & @CR & "2) priority" & @CR & "3,4,5,...) list of processes to check for" & @CR & "" & @CR & "The argument which determines what priority to set" & @CR & "0 - Idle/Low" & @CR & "1 - Below Normal (Not supported on Windows 95/98/ME)" & @CR & "2 - Normal" & @CR & "3 - Above Normal (Not supported on Windows 95/98/ME)" & @CR & "4 - High" & @CR & "5 - Realtime (Use with caution, may make the system unstable)" & @CR & @CR & "Example:" & @CR & @AutoItExe & " 30 0 firefox.exe notepad.exe acrotray.exe"

if int($CmdLine[0]) < 3 Then
    MsgBox(0, "Process_Check usage:", $usage);
    Exit
EndIf

Dim $interval = int($CmdLine[1])
Global $priority = int($CmdLine[2])
Global $plist[$CmdLine[0] - 2]
Global $i
for $i = 3 to $CmdLine[0]
;MsgBox(0, $i, $CmdLine[$i])
    $plist[$i - 3] = $CmdLine[$i]
Next

AdlibEnable("Process_Watch", $interval*1000)
_ReduceMemory()

while 1
    sleep (1000)
WEnd

Func Process_Check()

    for $i = 0 to UBound($plist) - 1
;MsgBox(0,$i,$plist[$i])
        if ProcessExists($plist[$i]) Then
    ;MsgBox(0,"Process_Check", $plist[$i] & " set to " & $priority)
            ProcessSetPriority($plist[$i], $priority)
        EndIf
    Next
    _ReduceMemory()
EndFunc

Func _ReduceMemory($i_PID = -1)
    If $i_PID <> -1 Then
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf
    
    Return $ai_Return[0]
EndFunc;==> _ReduceMemory()

Proc_Watch.zip

Edited by jftuga

Share this post


Link to post
Share on other sites



OK, I have found a fix for the SYSTEM account problem...

I added this code just above the AdlibEnable() statement:

if -1 == $interval then
        Process_Check()
        exit
endif

Now, I can run the program from a Scheduled Task as the SYSTEM account. It now has the ability to change the priority of other processes running under the same user account, SYSTEM. To do this, I simply pass -1 as the command-line argument.

-John

Share this post


Link to post
Share on other sites

I have updated this code and fixed a small bug.

I have attached a zip file including the source and executable.

Here are then new, updated comments...

-John

#cs

Proc_Watch
Set priority of a given list of processes
Originally written to help antivirus scanners not hog CPU during a full scan
-John Taylor
July-30-2005 - original
March-15-2007 - updated

Command-line options (all mandatory):
1) time interval in seconds to check for the list of processes
   use -1 to run immediately and then exit
2) priority
3,4,5,...) list of processes to check for & then change the priority

The argument which determines what priority to set
0 - Idle/Low
1 - Below Normal (Not supported on Windows 95/98/ME)
2 - Normal
3 - Above Normal (Not supported on Windows 95/98/ME)
4 - High
5 - Realtime (Use with caution, may make the system unstable)

Note: if you are trying to change the priority of a process running as the SYSTEM account,
      run this program from a Schedule Task as user SYSTEM.
      Scheduled Task Example: Proc_Watch.exe 60 0 fssm32.exe rtvscan.exe nod32.exe
      which means check every 60 seconds for these 3 process names and change their priority to the lowest possible

#ce

Proc_Watch.zip

Share this post


Link to post
Share on other sites

Great work on this.Its awesome to see just how powerful autoit can be.Thanks for the great script.

Share this post


Link to post
Share on other sites

As xStylezx says, superb work on this. I've been using this to drop the priority of my vmware Kubuntu virtual machine for several weeks now - it's been a godsend, particularly in conjunction with scheduled tasks.

Quick query though - Could it be easily modified to cope with multiple instances of the same process?

I recently upgraded to a core2quad (the G0 stepping processors are superb by the way), now running two virtual machines. However Proc_Watch only alters the priority of one of them.

Share this post


Link to post
Share on other sites

I am not sure if the script can be modified to handle multiple processes with the same name. The issue is with the ProcessSetPriority() function. We would have to ask one of the AutoIt developers if this works on all processes with the same name or not. If it does not, maybe they can modify the function so that it can optionally reprioritize all processes with the same name.

-John

Share this post


Link to post
Share on other sites

I am not sure if the script can be modified to handle multiple processes with the same name. The issue is with the ProcessSetPriority() function. We would have to ask one of the AutoIt developers if this works on all processes with the same name or not. If it does not, maybe they can modify the function so that it can optionally reprioritize all processes with the same name.

-John

I haven't looked at your code, but if you use ProcessList(Name) it returns a two dimension array of names and pid, match name and ProcessSetPriority(PID). I think that should work.

Talking Clockhttp://www.autoitscript.com/forum/index.php?showtopic=20751Talking Headlineshttp://www.autoitscript.com/forum/index.php?showtopic=20655Sometimes, I sits and thinkssometimes, I just sits

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

This program was modified for my particular usage a little while back, since other people are interested in the multiple instance of a process issue, here you go!

#cs

Proc_Watch
Set priority of a given list of processes to a specified priority level
Original Author: John Taylor (July-30-2005 - original, March-15-2007 - updated)
Modified by: WiSp (add code to handle multiple processes by the same name, added/cleaned up comments)

For history see URL: http://www.autoitscript.com/forum/index.php?showtopic=14187

Command-line options - Required:
1) Time between checks for processes
2) Priority to set them to
3) each processes to check for separated by spaces

Priority levels as defined by Windows 2000, XP and 2003:
0 - Idle/Low
1 - Below Normal (Not supported on Windows 95/98/ME) (Recommended)
2 - Normal
3 - Above Normal (Not supported on Windows 95/98/ME)
4 - High
5 - Realtime (Use with caution, may make the system unstable)

#ce

#include <GUICONSTANTS.au3>
#include <Process.au3>
#notrayicon
Opt ("GUIOnEventMode", 1)
Opt ("RunErrorsFatal", 0 )

;;; define what will be displayed to the user if no arguments are defined at run time -Will
Dim $usage = "Command-line options - Required:" & @CR & "1) Time between checks for processes" & @CR & "2) Priority to set them to" & @CR & "3) Each processes to check for separated by spaces" & @CR & "" & @CR & "Priority levels as defined by Windows 2000, XP and 2003:" & @CR & "0 - Idle/Low" & @CR & "1 - Below Normal (Not supported on Windows 95/98/ME) (RECOMMENDED)" & @CR & "2 - Normal" & @CR & "3 - Above Normal (Not supported on Windows 95/98/ME)" & @CR & "4 - High" & @CR & "5 - Realtime (Use with caution, may make the system unstable)" & @CR & @CR & "Example:" & @CR & @AutoItExe & " 30 0 firefox.exe notepad.exe acrotray.exe"

;;; check to see if the command line had the proper number of arguments otherwise put up the usage screen. -Will
if int($CmdLine[0]) < 3 Then
    MsgBox(0, "Process_Check usage:", $usage);
    Exit
EndIf

Dim $interval = int($CmdLine[1])        ; Set the $interval varable to the first command line argument
Global $priority = int($CmdLine[2])     ; Set the $priority to the second command line argument
Global $plist[$CmdLine[0] - 2]          ; everything else listed from this point on will be put into this array as processes to be looked for
for $i = 3 to $CmdLine[0]               ; this is taking in every other command line argument and putting them into the array -Will
    ;MsgBox(0, $i, $CmdLine[$i])
    $plist[$i - 3] = $CmdLine[$i]
Next

AdlibEnable("Process_Check", $interval*1000)    ; Start looking for processes, $interval * 1000 turns it into seconds. -Will
_ReduceMemory()                                 ; Run trash collection -Will

;;; not sure what purpose this serves but, if it ain't broke... -Will
while 1
    sleep (1000)
WEnd

;;; This is the real meat of the program
Func Process_Check()
    for $i = 0 to UBound($plist) - 1                        ; start at the beginning of the define processes to look for and start looping through them
        ;MsgBox(0,$i,$plist[$i])
        If ProcessExists($plist[$i]) Then                   ; if this process exists (is actually running),...
            _AdjustPriority($plist[$i])                     ; then run the _AdjustPriority function and supply the name of the ProcessClose
        EndIf
    Next
    _ReduceMemory()                                         ; Garbage collection
EndFunc


Func _AdjustPriority($plist)
        $alist = ProcessList($plist)                            ; Look for the process name and make an array of all instances and pids
        For $i = 1 to $alist[0][0] step 1                       ; for each instance,
            $var = _ProcessGetPriority ($alist[$i][1])          ; get the current priority of this particular instance (by pid)
            If $var <> $priority Then                           ; If the instance's priority is not equal to what we want...
                ProcessSetPriority($alist[$i][1], $priority)    ; then set the priority ot what we defined, otherwise "NEXT!"
            EndIf
        Next
EndFunc

Func _ReduceMemory($i_PID = -1)
    If $i_PID <> -1 Then
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf
    
    Return $ai_Return[0]
EndFunc;==> _ReduceMemory()[/font]
Edited by WiSp

Share this post


Link to post
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
Sign in to follow this  
Followers 0