开发者

Start long running background process and check the status

开发者 https://www.devze.com 2023-03-28 17:37 出处:网络
I want to start a potentially long running background process from Delphi. I want to leave the process running independently, but first I want to check that the process started OK.

I want to start a potentially long running background process from Delphi. I want to leave the process running independently, but first I want to check that the process started OK.

If anything went wrong on startup, I want to capture any output written to standardErr and log it. If the background process starts OK, my program needs to be able to exit and leave the spawned process running.

The psuedo code would be something like this:

process:=RunProgramInBackground('someCommand.exe');
sleep(1000); // Wait a bit to see if the program started OK
if process.Finished and process.ExitCode=FAIL then 
    Raise Exception.Create(process.ErrorStream);
process.Disp开发者_JAVA技巧ose; // Close any connection we may still have to the running process
Program.Exit; // Background process keeps running

I've looked at a few things (WinExec, CreateProcess, ShellExecute, JclMiscel) but can't find any examples for what I'm trying to do. What is the best way to do this?

I'm using Delphi 2010

The background process is a 3rd party program I don't have the source to.


Check out this article. I quote: "Here is an updated and improved version of the code that allows you to choose in code whether the calling application waits until the other program closes before continuing or just carries on leaving the newly started program to its own devices".

procedure ExecNewProcess(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+NORMAL_PRIORITY_CLASS,
                    nil, nil, StartInfo, ProcInfo);
 { check to see if successful } 
 if CreateOK then
  begin
    //may or may not be needed. Usually wait for child processes 
   if Wait then
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
  end
 else
  begin
   ShowMessage('Unable to run '+ProgramName);
  end;

 CloseHandle(ProcInfo.hProcess);
 CloseHandle(ProcInfo.hThread);
end;

Edited: after reading your comments, I suggest that you look at this previous question


I ended up using the example No'Am linked to, and adding code to check that the process started OK. This function only checks the exit code of the background process, it doesn't read the StdErr output.

Here is what I did:

/// <summary> Runs a new process in the background. Waits for a short period, then checks that the process started succesfully.
/// If the process has already finished, checks the exit status. Otherwise, leaves it to run. </summary>
/// <param> ProgramName The executable name, including any parameters.</param>
/// <param> TimeOut Milliseconds to wait before checking the process has executed correctly</param>
/// <param> Directory The full path of the working directory</param>
/// <exception> Exception If the process was not started correctly or if the process was started but returned
/// an error before the timeout.</exception>
procedure ExecBackgroundProcess(ProgramName : String; TimeOut: Integer; Directory:string);
var
    StartInfo : TStartupInfo;
    ProcInfo : TProcessInformation;
    CreateOK : Boolean;
    status: Cardinal;
    theExitCode: Cardinal;
begin
    FillChar(StartInfo,SizeOf(TStartupInfo),#0);
    FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
    StartInfo.cb := SizeOf(TStartupInfo);
    UniqueString(ProgramName); // Required if a const string is passed in. Otherwise the program crashes.
    CreateOK := CreateProcess(nil, PChar(ProgramName), nil, nil,False,
              CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS+CREATE_NO_WINDOW,
              nil, PChar(Directory), StartInfo, ProcInfo);

    if CreateOK then
    begin
        status:=WaitForSingleObject(ProcInfo.hProcess, TimeOut);
        if status<> WAIT_TIMEOUT then
        begin
            // Program has exited. Get exit code.
            GetExitCodeProcess(ProcInfo.hProcess, theExitCode);
            if theExitCode<>0 then raise Exception.Create('Program '''+ProgramName+''' failed with exit code '+IntToStr(theExitCode));
        end
    end
    else
      Raise Exception.Create('Unable to run '+ProgramName+' in directory '+Directory);

    CloseHandle(ProcInfo.hProcess);
    CloseHandle(ProcInfo.hThread);
end;
0

精彩评论

暂无评论...
验证码 换一张
取 消