How can I wait for the external process to complete?

So, I made a form in Delphi that allows me to run various sikuli scripts with different configurations. Now I am working on making someone use the form to configure various sikuli scripts to run differently. How in:

Step 1: SikuliScript1 with ConfigFile1. Step 2: SikuliScript2 with ConfigFile2. etc ... This is my code:

procedure TSikRunForm.btnRunClick(Sender: TObject); begin DirCombo:= '/C '+DirSik+'\sikuli-script.cmd' +' -r ' + DirScript + ' --args '+DirConfig; if SikFound then begin ShellExecute(Handle, nil, 'cmd.exe', pChar(DirCombo), nil, SW_SHOWNORMAL); Application.minimize; end else begin ShowMessage('Select the correct folder for your Sikuli installation folder'); end; end; 

And this works great, the siculi script works fine, and during operation the cmd line is visible with the various actions shown. After running the sikuli script, the cmd line closes by itself. Therefore, the shell handler knows when to complete the running process. So my question is: can I tell delphi: after the handler has finished the process, start the next process (Sikuli Script)? Now I know that I can work with all createProcess in delphi, but that just seems redundant. There must be a way to make it faster and easier. Does anyone have a key?

+7
source share
4 answers

With CreateProcess you can get the handle of the process, and with WaitForSingleObject you can check when the process is complete. I use the following function, this runs the command in the background:

 procedure ExecuteAndWait(const aCommando: string); var tmpStartupInfo: TStartupInfo; tmpProcessInformation: TProcessInformation; tmpProgram: String; begin tmpProgram := trim(aCommando); FillChar(tmpStartupInfo, SizeOf(tmpStartupInfo), 0); with tmpStartupInfo do begin cb := SizeOf(TStartupInfo); wShowWindow := SW_HIDE; end; if CreateProcess(nil, pchar(tmpProgram), nil, nil, true, CREATE_NO_WINDOW, nil, nil, tmpStartupInfo, tmpProcessInformation) then begin // loop every 10 ms while WaitForSingleObject(tmpProcessInformation.hProcess, 10) > 0 do begin Application.ProcessMessages; end; CloseHandle(tmpProcessInformation.hProcess); CloseHandle(tmpProcessInformation.hThread); end else begin RaiseLastOSError; end; end; 
+19
source

You need to wait until the process handle is signaled. For example, by calling WaitForSingleObject. Obviously, CreateProcess returns you a handle to the process on which you can wait. You cannot convince ShellExecute to return the handle to the process, but its more capable brother ShellExecuteEx will do it.

However, I personally chose CreateProcess here. You will get more flexibility and control, and it is not so difficult. For example, you can turn off the display of the console window if you want.

+5
source

Well, I looked at it more and decided it, as David suggested. I will show what I did if anyone has any questions or something else:

 procedure TSikRunForm.btnRunClick(Sender: TObject); begin CmdLine:= 'C:\\windows\\system32\\cmd.exe'; uniqueString(CmdLine); if SikFound then begin //----------For loop--------------- DirScript:= TScriptEdit.Text; DirConfig:= TConfEdit.Text; DirCombo:= '/C '+DirSik+'\sikuli-script.cmd' +' -r ' + DirScript + ' --args '+DirConfig; CreateProcess(PChar(CmdLine),PChar(DirCombo),Nil,Nil,False,CREATE_NO_WINDOW,nil,nil,StartInfo,ProcInfo); procHandle:= ProcInfo.hProcess; Application.minimize; WaitForSingleObject(procHandle, INFINITE); DirScript:= TScriptEdit2.Text; DirConfig:= TConfEdit2.Text; DirCombo:= '/C '+DirSik+'\sikuli-script.cmd' +' -r ' + DirScript + ' --args '+DirConfig; CreateProcess(PChar(CmdLine),PChar(DirCombo),Nil,Nil,False,CREATE_NO_WINDOW,nil,nil,StartInfo,ProcInfo); procHandle:= ProcInfo.hProcess; Application.minimize; WaitForSingleObject(procHandle, INFINITE); //---------------------------------------- showMessage('Gedoan'); end else begin ShowMessage('Select the correct folder for your Sikuli installation folder'); end; end; 

It works exactly as I wanted. 2 sikuli scripts will run one after another.

+1
source

This is a hack and makes it less complicated, but maybe you can just generate a * .bat file containing script calls, using "start / wait" on each line if necessary.

0
source

All Articles