How to get the information that a specific process has been terminated?

Get help with using AutoHotkey and its commands and hotkeys
newbieforever
Posts: 400
Joined: 24 Aug 2016, 03:34

How to get the information that a specific process has been terminated?

06 Apr 2019, 09:33

Hi!

Is there a way for a script to get the information that a specific process has been terminated? I mean an alternative to a periodical check if the process still exists.
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to get the information that a specific process has been terminated?

06 Apr 2019, 10:38

Detect process start/end:
New Process Notifier - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/56984-new-process-notifier/
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
newbieforever
Posts: 400
Joined: 24 Aug 2016, 03:34

Re: How to get the information that a specific process has been terminated?

06 Apr 2019, 11:44

@jeeswg:

Thank you very much!

I see, this would be a solution. For my specific purpose however it is a too complex script. In my case only the termination of a specific AHK script should be detected. Maybe another solution for this?
AHKStudent
Posts: 651
Joined: 05 May 2018, 12:23

Re: How to get the information that a specific process has been terminated?

06 Apr 2019, 17:53

newbieforever wrote:
06 Apr 2019, 11:44
@jeeswg:

Thank you very much!

I see, this would be a solution. For my specific purpose however it is a too complex script. In my case only the termination of a specific AHK script should be detected. Maybe another solution for this?
maybe https://www.autohotkey.com/docs_1.0/commands/OnExit.htm
SOTE
Posts: 838
Joined: 15 Jun 2015, 06:21

Re: How to get the information that a specific process has been terminated?

06 Apr 2019, 19:03

newbieforever wrote:
06 Apr 2019, 09:33
Hi!

Is there a way for a script to get the information that a specific process has been terminated? I mean an alternative to a periodical check if the process still exists.
In reading this, it's a bit tricky. Not all applications are the same. Some apps are meant to run continuously, some are interactive with the user, and others are meant to do some specified task that will take an unknown period of time to complete.

It you wrote the script, then you can have it log when completed. If you want to watch some other process, I would think a periodical check with Process, Exist would be fine for the vast majority of purposes.

Maybe you need to explain more about what you are trying to do, where using SetTimer with Process, Exist would not work. For instance, you might want to know if a service has stopped working versus if an application has finished.
newbieforever
Posts: 400
Joined: 24 Aug 2016, 03:34

Re: How to get the information that a specific process has been terminated?

07 Apr 2019, 04:39

Thank you, jeeswg & SOTE, for your answers.

I'm following another idea right now.

Right from the start I was thinking about a solution with OnMessage. Now I actually found out that every running program in Windows has a hidden window. (I'm not sure if "every" is really correct, but at least for AHK scripts this should be true.) The title of the hidden window of a running AHK script contains the full path of this script. So when an AHK script is closed, its hidden window is destroyed. And this can be detected via OnMessage!

Below is a demo script that illustrates this. In my tests this solution works perfectly so far.

My question to you AHK experts would be how to judge this solution: good and reliable, questionable, elegant or inelegant? Above all, however, I would also be interested to know how resource-intensive this solution is compared to a simple timer solution. I would assume that a timer would mean significantly more CPU load.

Code: Select all

#Persistent

; AhkScriptFullPath :=          ; The full path of the AHK script which termination should be detected

DetectHiddenWindows, ON
Gui +LastFound
DllCall("RegisterShellHookWindow", UInt, WinExist())
MsgNum := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
OnMessage(MsgNum, "ShellMessage")

RETURN

ShellMessage(wParam, lParam) {
  If (wParam = 2) {                             ; HSHELL_WINDOWDESTROYED := 2
    lParam := Dec2hex(lParam)
    WinGetTitle, Title, ahk_id %lParam%
    ; If InStr(Title, AhkScriptFullPath)
    MsgBox WINDOWDESTROYED: %Title%
    }
  }

Dec2hex(n) 
{
   oIF := A_FormatInteger
   SetFormat, Integer, hex
   n := StrLen(n+0) ? n+0 : n
   SetFormat, Integer, % oIF
   Return n
}
User avatar
lvalkov
Posts: 39
Joined: 08 Mar 2019, 16:39

Re: How to get the information that a specific process has been terminated?

07 Apr 2019, 19:14

You could pass a PID to RegisterWaitForSingleObject() and do your processing in the callback, which will be fired upon the process's termination. Error handling, checking and recovery omitted for brevity. GlobalAlloc() used for more persistent heap allocation, although you could probably manage with the built-in facilities (Ptr*, VarSetCapacity()) if you're fine with keeping track of them.

Code: Select all

#Persistent

Run % "notepad.exe", , , pid
WinWait % "ahk_pid" pid

hProcess := DllCall("OpenProcess", "UInt", 0x00100000, "Int", false, "UInt", pid, "Ptr") ; SYNCHRONIZE 0x00100000
Callback := RegisterCallback("WaitOrTimerCallback")
hWaitObj := DllCall("GlobalAlloc", "UInt", 0x40, "UPtr", dwBytes, "Ptr") ; GMEM_FIXED 0x0000, GMEM_ZEROINIT 0x0040
DllCall("RegisterWaitForSingleObject", "Ptr", hWaitObj, "Ptr", hProcess, "Ptr", Callback, "Ptr", hWaitObj, "UInt", 0xFFFFFFFF, "UInt", 0x00000008) ; INFINITE 0xFFFFFFFF, WT_EXECUTEONLYONCE 0x00000008
DllCall("CloseHandle", "Ptr", hProcess)

MsgBox % "Press OK to close Notepad."
Process Close, % pid

WaitOrTimerCallback(lpParameter, TimerOrWaitFired) {
	Critical ; Required.

	/*
		Do work here.
	*/
	MsgBox % "Notepad has closed."

	/*
		Free resources when done. Mandatory.
	*/
	hWaitObj := NumGet(lpParameter + 0) ; Handle passed through RWFSO's Context parameter.
	DllCall("UnregisterWait", "Ptr", hWaitObj) ; Even WT_EXECUTEONLYONCE Waits have to be unregistered.
	DllCall("GlobalFree", "Ptr", hWaitObj, "Ptr") ; Frees memory allocated by GlobalAlloc().
	DllCall("GlobalFree", "Ptr", A_EventInfo, "Ptr") ; Frees memory allocated by RegisterCallback().

	ExitApp
}

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], Chunjee, flyingDman, vakacjus and 220 guests