Starting a process and listening for exit event
Asked Answered
T

1

6

I have some code that starts a process and hooks up an event handler to handle when the process exits, the code I have is written in C# and I wonder if something similar is possible with Delphi.

System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
myProcess.StartInfo.FileName = "notepad.exe";
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new System.EventHandler(Process_OnExit);
myProcess.Start();

public void Process_OnExit(object sender, EventArgs e)
{
    //Do something when the process ends
}

I don't know much about Delphi so any help would be appreciated, thanks.

Trespass answered 5/1, 2010 at 19:32 Comment(0)
C
9

Yes, you can do something similar with Delphi. I have not seen using an event handler, but you can create a process, wait for it to finish, and then do something when that happens. Put it in another thread if you want to do something in the meantime.

Here is some code for creating a process and waiting that I scraped off the net:

procedure ExecNewProcess(const ProgramName : String; Wait: Boolean);
var
  StartInfo : TStartupInfo;
  ProcInfo : TProcessInformation;
  CreateOK : Boolean;
begin
  { fill with known state } 
  FillChar(StartInfo, SizeOf(TStartupInfo), 0);
  FillChar(ProcInfo, SizeOf(TProcessInformation), 0);
  StartInfo.cb := SizeOf(TStartupInfo);
  CreateOK := CreateProcess(nil, PChar(ProgramName), nil, nil, False,
              CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS,
              nil, nil, StartInfo, ProcInfo);
   { check to see if successful } 
  if CreateOK then
    begin
      //Note: This will wait forever if the process never ends! 
      // You are better off using a loop with a timeout, or WaitForMultipleObject 
      if Wait then
        WaitForSingleObject(ProcInfo.hProcess, INFINITE);
    end
  else
    begin
      RaiseLastOSError;
      //SysErrorMessage(GetLastError());
    end;

  CloseHandle(ProcInfo.hProcess);
  CloseHandle(ProcInfo.hThread);
end;
Coworker answered 5/1, 2010 at 20:18 Comment(6)
I would not use INFINITE but a timeout and a loop to be able to interrupt the wait if needed, or WaitForMultipleObject() with an event to exit the wait. Otherwise it could be impossible to terminate the waiting thread cleanly. Also if CreateProcess() fails, don't hide the error emitting a generic, useless message, but call RaiseLasOSError to show the real error.Capricorn
Another hint: FilLChar last parameter does not need to be a char - it could be a byte. To avoid Unicode issues, if you're just filling a binary struct with zeroes, pass 0, not #0.Capricorn
Both good advice @ldsandon. I have done both in production code.Coworker
@Jim: When combining bits in flags, you should always use OR instead of +. You're operating at the bit-flag level, and addition may give you different results than a binary OR.Eructate
I would put "const" before ProgramName in the parameter listPractical
Note the incoming "ProgramName" will need to be double quoted. If it is not then if there is a Space in the path such as "program files" and the person has an executable named "program" in the path, it will be executing that instead. Without the quotes this would be a security vulnerability. learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/…Marlie

© 2022 - 2024 — McMap. All rights reserved.