delphi - tierra - ¿Cómo puedo esperar hasta que se complete un proceso externo?
procesos geologicos internos (4)
Con CreateProcess puede obtener un identificador de proceso y con WaitForSingleObject puede verificar cuándo se completa el proceso. Utilizo la siguiente función, esto ejecuta el comando en segundo plano:
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;
Así que hice un formulario en Delphi que me permite ejecutar varios scripts sikuli con varias configuraciones. Lo que estoy trabajando ahora es hacer posible que alguien use el formulario, para configurar varios scripts de sikuli para que se ejecuten uno tras otro. Como en:
Paso 1: SikuliScript1 con ConfigFile1. Paso 2: SikuliScript2 con ConfigFile2. etc ... Este es mi código hasta ahora:
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;
Y esto funciona perfecto, la secuencia de comandos de sikuli se ejecuta perfectamente, y mientras se ejecuta, la línea de cmd es visible con las diversas acciones que se muestran que se están realizando. Después de que la secuencia de comandos de sikuli está lista, la línea de cmd se cierra por sí misma. Entonces, el manejador de shell sabe cuándo cerrar el proceso en ejecución. Entonces mi pregunta es: ¿es posible decir delphi: después de que el controlador haya cerrado el proceso, ejecute el siguiente proceso (Sikuli Script)? Ahora sé que puedo ir con todo el createProcess en Delphi, pero parece excesivo. Tiene que haber una forma de hacerlo más rápido y más fácil. Alguien tiene una pista?
Debe esperar hasta que se indique el identificador del proceso. Por ejemplo, mediante una llamada a WaitForSingleObject. Obviamente, CreateProcess le devuelve un identificador de proceso en el que puede esperar. No puede convencer a ShellExecute de que devuelva un identificador de proceso, pero su hermano más capaz, ShellExecuteEx, lo hará.
Sin embargo, yo personalmente elegiría CreateProcess aquí. Obtendrá más flexibilidad y control, y no es tan complejo. Por ejemplo, puede suprimir la visualización de la ventana de la consola si lo desea.
Este es un truco y es menos sofisticado, pero tal vez podrías generar un archivo * .bat que contenga las llamadas a los guiones, si es necesario usando "iniciar / esperar" en cada línea.
Ok, he investigado más sobre esto y lo he resuelto, tal como sugirió David. Mostraré lo que hice, si alguien más tiene alguna pregunta o algo:
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;
Funciona exactamente como yo quería. Los 2 scripts de sikuli se ejecutarán uno tras otro.