Script that Checks for processes without using Infinite Loop Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
PercyPierce
Posts: 9
Joined: 31 Mar 2017, 22:52

Script that Checks for processes without using Infinite Loop

01 Apr 2017, 16:05

Hi Guys! How You all doing tonight?
I need a little help with a piece of code that I have a problem with.

I create a master script that runs all by itself. but I want it to open other scripts when certain processes are open, and close the same scripts when the certain process closes (or is not opened).




Code: Select all

#persistent ;just added this in because without it, the master script will terminate on its own. Don't understand why

notepadon = 0
Loop ;this will be my code to check whether or not a process is running or if a variable is a certain value. Not unlike Gamemaker Studio's "step" event which was my entrypoint into coding.
{
	If ProcessExist("notepad.exe") && notepadon == 0 
	{
		
		Run, open "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk" ;runs this ahk file when notepade opens.
		notepadon = 1 ;stop creating more instances of the script but DO NOT terminate the loop.
	}
	If !ProcessExist("notepad.exe") && notepadon == 1 
	{
		DetectHiddenWindows, On 
		WinClose, "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk"  ;I am still working on getting this function to work.
		notepadon = 0 ;reset the variable so that if I re-open notepad, this script will re-open the "Delate" ahk script.
	}

}


ProcessExist(Name)
{
	Process,Exist,%Name%
	return Errorlevel
}


return


Ok. So WHen I view it in task manager, it is taking up about 10 percent of the cpu power! whereas way more advanced scripts such as those that allow you to scroll inactive windows uses up 0%.
Without this loop function, It only works when I first open the master script. is there a less processor intensive alternative to this code?
Last edited by PercyPierce on 01 Apr 2017, 16:14, edited 1 time in total.
User avatar
tomoe_uehara
Posts: 213
Joined: 05 Oct 2013, 12:37
Contact:

Re: Script that Checks for processes without using Infinite Loop

01 Apr 2017, 16:11

I think you can reduce the CPU usage by adding a Sleep, or just use SetTimer.
Your Loop is running endlessly and eating your CPU resources.
PercyPierce
Posts: 9
Joined: 31 Mar 2017, 22:52

Re: Script that Checks for processes without using Infinite Loop

01 Apr 2017, 16:17

You mean reduce the many times it loops per second? When I put more if statements along with this one after I decrease the infinite loop refresh rate, will it increase the overhead?
User avatar
tomoe_uehara
Posts: 213
Joined: 05 Oct 2013, 12:37
Contact:

Re: Script that Checks for processes without using Infinite Loop

01 Apr 2017, 17:07

Well, your Loop works like 10ms (or so) per cycle, if you add a Sleep on it, it will reduce the amount of cycle per second.
Several IFs won't hurt the performance so much, but the speed of your Loop is what really matters.
Or you can try to use IfWinExist command, but it can't determine from PID, it can only read WinTitle & WinText.
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Script that Checks for processes without using Infinite Loop

01 Apr 2017, 17:29

Use Process, Wait andProcess, WaitClose commands (see: https://www.autohotkey.com/docs/commands/Process.htm).

Code: Select all

Loop
{
	Process, Wait, notepad.exe
	PID := ErrorLevel
	Run % "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk",, AHKPID
	Process, WaitClose, % PID
	DetectHiddenWindows, On 
	WinClose % "ahk_pid " . AHKPID
}
my scripts
PercyPierce
Posts: 9
Joined: 31 Mar 2017, 22:52

Re: Script that Checks for processes without using Infinite Loop

01 Apr 2017, 22:06

Hmm. For some reason your code didn't cause the master script to close out the delate script when I closed Notepad.

I updated my version of the code. and I got the "delate" script to close.
I found a problem with just using process, wait.

Code: Select all

#Persistent

notepadon = 0
excelon = 0 ; new variable for microsoft excel.
Loop
{
				if (notepadon == 0)
				{
					process, wait, Notepad.exe
					{
						
						Run, open "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk"
						notepadon = 1
					}
					
				}
				if (notepadon == 1)
				{
				If !ProcessExist("Notepad.exe")
					{
						DetectHiddenWindows, On
						WinClose, C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk
						notepadon = 0
					}
				}
}
Loop
{
				if (excelon == 0)
				{
					process, wait, EXCEL.EXE
					{
						
						Run, open "C:\Users\Owner\Desktop\Scroll Horizontally while Holdint the Right Mouse Button.ahk" 
						excelon = 1
					}
					
				}
				if (excelon == 1)
				{
				If !ProcessExist("EXCEL.EXE")
					{
						DetectHiddenWindows, On
						WinClose, C:\Users\Owner\Desktop\Scroll Horizontally while Holdint the Right Mouse Button.ahk
						excelon = 0
					}
				}


}



ProcessExist(Name){
	Process,Exist,%Name%
	return Errorlevel
}


return
Now the FIRST loop works perfectly. That is, the ahk script opens and closes along with notepad.
I found that (hypothetically) loop isn't the culprit to the massive cpu load, it is the declared function. But I might still need that declared function.
How do you guys get process wait to work as many times as needed in a script? if that's even possible.
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Script that Checks for processes without using Infinite Loop

01 Apr 2017, 23:07

To save system resources you can use a hook, that will be called by the OS whenever a (new) window activates.
  • there is no more need to continually monitor
  • put your checking code into a "Guard" function

Code: Select all

SetBatchLines, -1
notepadon := 0
Script := "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk"
Return



;-------------------------------------------------------------------------------
Watchdog(wParam, lParam="") { ; calls the guard
;-------------------------------------------------------------------------------
    ; HSHELL_WINDOWCREATED      = 1
    ; HSHELL_WINDOWACTIVATED    = 4
    ; HSHELL_RUDEAPPACTIVATED   = 32772 (fullscreen app activated)
    ;---------------------------------------------------------------------------
    static init   := DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd)
        , MsgNum  := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
        , neglect := OnMessage(MsgNum, "Watchdog")
        , CleanUp := {base: {__Delete: "Watchdog"}}

    If ! CleanUp {
        OnMessage(MsgNum, "")
        DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
    }

    If (wParam = 1 Or wParam = 4 Or wParam = 32772)
        Guard(lParam)
}



;-------------------------------------------------------------------------------
Guard(hWnd) { ; code to check ...
;-------------------------------------------------------------------------------
    global notepadon, Script
    static PID

    If WinExist("ahk_exe notepad.exe") and (notepadon = 0) {
        Run, %Script%,, PID
        notepadon := 1
    {

    If !WinExist("ahk_exe notepad.exe") and (notepadon = 1) {
        WinClose, ahk_pid %PID%
        notepadon := 0
    }
}
I hope that helps.
(Written before excelon was first mentioned)
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Script that Checks for processes without using Infinite Loop  Topic is solved

01 Apr 2017, 23:19

Try this:

Code: Select all

SetBatchLines, -1
notepadon := 0
exelon := 0
Script1 := "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk"
Script2 := "C:\Users\Owner\Desktop\Scroll Horizontally while Holdint the Right Mouse Button.ahk"
Return



;-------------------------------------------------------------------------------
Watchdog(wParam) { ; calls the guard
;-------------------------------------------------------------------------------
    ; HSHELL_WINDOWCREATED      = 1
    ; HSHELL_WINDOWACTIVATED    = 4
    ; HSHELL_RUDEAPPACTIVATED   = 32772 (fullscreen app activated)
    ;---------------------------------------------------------------------------
    static init   := DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd)
        , MsgNum  := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
        , neglect := OnMessage(MsgNum, "Watchdog")
        , CleanUp := {base: {__Delete: "Watchdog"}}

    If Not IsObject(CleanUp) {
        OnMessage(MsgNum, "")
        DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
    }

    If (wParam = 1 Or wParam = 4 Or wParam = 32772)
        Guard()
}



;-------------------------------------------------------------------------------
Guard() { ; code to check ...
;-------------------------------------------------------------------------------
    global notepadon, Script1, exelon, Script2
    static PID_notepad, PID_excel

    If WinExist("ahk_exe notepad.exe") and (notepadon = 0) {
        Run, %Script1%,, PID_notepad
        notepadon := 1
    {

    If !WinExist("ahk_exe notepad.exe") and (notepadon = 1) {
        WinClose, ahk_pid %PID_notepad%
        notepadon := 0
    }

    If WinExist("ahk_exe EXCEL.EXE") and (exelon = 0) {
        Run, %Script2%,, PID_excel
        exelon := 1
    {

    If !WinExist("ahk_exe EXCEL.EXE") and (exelon = 1) {
        WinClose, ahk_pid %PID_excel%
        exelon := 0
    }
}
I hope that helps.
PercyPierce
Posts: 9
Joined: 31 Mar 2017, 22:52

Re: Script that Checks for processes without using Infinite Loop

02 Apr 2017, 13:19

Thanks for your help guys.
Wolf, your script was the best so far.
Here's how I fixed it up.

Code: Select all

SetBatchLines, -1
notepadon := 0
exelon := 0
Script1 := "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk"
Script2 := "C:\Users\Owner\Desktop\Scroll Horizontally while Holdint the Right Mouse Button.ahk"
Return



;-------------------------------------------------------------------------------
Watchdog(wParam) { ; calls the guard
;-------------------------------------------------------------------------------
    ; HSHELL_WINDOWCREATED      = 1
    ; HSHELL_WINDOWACTIVATED    = 4
    ; HSHELL_RUDEAPPACTIVATED   = 32772 (fullscreen app activated)
    ;---------------------------------------------------------------------------
    static init   := DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd)
        , MsgNum  := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
        , neglect := OnMessage(MsgNum, "Watchdog")
        , CleanUp := {base: {__Delete: "Watchdog"}}

    If Not IsObject(CleanUp) {
        OnMessage(MsgNum, "")
        DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
    }

    If (wParam = 1 Or wParam = 4 Or wParam = 32772)
        Guard()
}



;-------------------------------------------------------------------------------
Guard() { ; code to check ...
;-------------------------------------------------------------------------------
    global notepadon, Script1, exelon, Script2
    static PID_notepad, PID_excel

    If WinExist("ahk_exe notepad.exe") and (notepadon = 0) {
        Run, %Script1%,, PID_notepad
        notepadon := 1
    }

    If !WinExist("ahk_exe notepad.exe") and (notepadon = 1) {
		DetectHiddenWindows , On
        WinClose, %Script1%
        notepadon := 0
    }

    If WinExist("ahk_exe EXCEL.EXE") and (exelon = 0) {
        Run, %Script2%,, PID_excel
        exelon := 1
    }
	
    If !WinExist("ahk_exe EXCEL.EXE") and (exelon = 1) {
		DetectHiddenWindows , On
        WinClose,  %Script2%
        exelon := 0
    }


}

I just had to replace Ahk_pId and pid[processname] with an old-fashioned variable recall because before the ahk scripts wouldn't close when i closed notepad or excel.
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Script that Checks for processes without using Infinite Loop

02 Apr 2017, 21:21

The Loop was correctly blamed by forum user tomoe_uehara for eating CPU resources.
The credit for recommending ShellHook over SetTimer goes to forum user SvenBent: https://autohotkey.com/boards/viewtopic ... 26#p109226.
My contribution is merely to create a function that can be plugged in between the auto-execute section of your original script and a second function that replaces your original Loop.

BTW, since you don't need the static variables in Guard() any more, you could just remove them.
Maybe you will be less likely to get confused in the future when reading the code. (Like I would)
Pintte

Re: Script that Checks for processes without using Infinite Loop

29 Aug 2018, 17:55

wolf_II wrote:Try this:

Code: Select all

SetBatchLines, -1
notepadon := 0
exelon := 0
Script1 := "C:\Users\Owner\Desktop\Delate Line of Text Behind the cursor.ahk"
Script2 := "C:\Users\Owner\Desktop\Scroll Horizontally while Holdint the Right Mouse Button.ahk"
Return



;-------------------------------------------------------------------------------
Watchdog(wParam) { ; calls the guard
;-------------------------------------------------------------------------------
    ; HSHELL_WINDOWCREATED      = 1
    ; HSHELL_WINDOWACTIVATED    = 4
    ; HSHELL_RUDEAPPACTIVATED   = 32772 (fullscreen app activated)
    ;---------------------------------------------------------------------------
    static init   := DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd)
        , MsgNum  := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
        , neglect := OnMessage(MsgNum, "Watchdog")
        , CleanUp := {base: {__Delete: "Watchdog"}}

    If Not IsObject(CleanUp) {
        OnMessage(MsgNum, "")
        DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
    }

    If (wParam = 1 Or wParam = 4 Or wParam = 32772)
        Guard()
}



;-------------------------------------------------------------------------------
Guard() { ; code to check ...
;-------------------------------------------------------------------------------
    global notepadon, Script1, exelon, Script2
    static PID_notepad, PID_excel

    If WinExist("ahk_exe notepad.exe") and (notepadon = 0) {
        Run, %Script1%,, PID_notepad
        notepadon := 1
    {

    If !WinExist("ahk_exe notepad.exe") and (notepadon = 1) {
        WinClose, ahk_pid %PID_notepad%
        notepadon := 0
    }

    If WinExist("ahk_exe EXCEL.EXE") and (exelon = 0) {
        Run, %Script2%,, PID_excel
        exelon := 1
    {

    If !WinExist("ahk_exe EXCEL.EXE") and (exelon = 1) {
        WinClose, ahk_pid %PID_excel%
        exelon := 0
    }
}
I hope that helps.
is there a way to stop the hook?

lets say i want a msgbox when a process starts, but then i want to hook to stop until process quits and then use the hook to wait again?

I do not like timers if there is another way, can i still do this using this guard>?

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 343 guests