Get notified when another application terminates (Views: 27)
Problem/Question/Abstract: My application is starting processes invoking ShellExecute API calls. These processes are manipulating files stored in a database BLOB field. I'd like to be notified when the external application terminates in order to save shanges made on the file. My idea was to use windows hooks, but I didn't guess exactly how. ShellExecute returns the Instance Handle of the application that was run (or DDE handle). Answer: Solve 1: How about using the WndProc procedure and listening for the WM_QUERYENDSESSION in the main application, and broadcasting another message to the other one. Then your applications do what they need to do when they receive the message. For example: {MainApp:} const EndAppMsg = $FFF8B; public procedure WndProc(var Msg: TMessage); override; procdure TMainForm.WndProc(var Msg: TMessage); begin if Msg.Msg = WM_QUERYENDSESSION then begin BroadcastSystemMessage(BSF_POSTMESSAGE, BSM_ALLCOMPONENTS, EndAppMsg, 0, 0) end else inherited; end; And then use the WndProc again in the other applications that the main application calls, and listen for the EndAppMsg message. When it is recived execute the code that you need to execute. For example: {Client/Worker App} procedure WndProc(var Msg: Tmessage); const EnaAppMsg = $FFF8B; begin if Msg.Msg = EndAppMsg then begin {Execute your code here or call another procedure to execute the code} end else inherited; end; Solve 2: You might try using ShellExecuteEx instead, then using the returned hProcess in a WaitForSingleObject call. Here's an example I used in a small demo application: uses Windows, ShellApi; var Info: TShellExecuteInfo; begin FillChar(Info, SizeOf(Info), 0); Info.cbSize := SizeOf(Info); Info.fMask := SEE_MASK_NOCLOSEPROCESS; Info.Wnd := Handle; Info.lpVerb := 'open'; Info.lpFile := 'C:\SomeTextFile.Text'; {Change me!} Info.lpParameters := nil; Info.lpDirectory := nil; Info.nShow := SW_SHOW; if (ShellExecuteEx(@Info)) then begin WaitForSingleObject(Info.hProcess, INFINITE); MessageBox(Handle, 'You closed the app I launched!', 'Finished!', MB_OK); CloseHandle(Info.hProcess); end; end; I'm not sure if you want your entire application becoming unresponsive while the launched application is running (the WaitForSingleObject call doesn't return until the application is closed), but if you don't, you might consider launching individual threads for each ShellExecuteEx, then using WaitForSingleObject in those threads (and writing an OnTerminate handler for the thread object to determine when the application finally finished). |