我怎么能等到外部过程完成?

时间:2013-06-27 06:41:39

标签: delphi winapi

所以我在Delphi中创建了一个表单,允许我运行各种配置的各种sikuli脚本。我现在正在做的是让使用该表单的人可以设置各种sikuli脚本以便一个接一个地运行。如:

步骤1:带ConfigFile1的SikuliScript1。 第2步:使用ConfigFile2的SikuliScript2。 等等... 到目前为止,这是我的代码:

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;

这很完美,sikuli脚本运行完美,并且在运行时,cmd线可以看到正在执行的各种动作。 sikuli脚本完成后,cmd行自行关闭。因此shell处理程序知道何时关闭正在运行的进程。所以我的问题是:是否有可能告诉delphi:在处理程序关闭进程后,运行下一个进程(Sikuli脚本)? 现在我知道我可以在delphi中使用整个createProcess,但它似乎有点矫枉过正。必须有一种方法来更快更容易地做到这一点。 任何人都有线索?

4 个答案:

答案 0 :(得分:23)

使用CreateProcess可以获得进程句柄,使用WaitForSingleObject可以检查进程何时完成。 我使用以下函数,它在后台运行命令:

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;

答案 1 :(得分:6)

您需要等到处理过程句柄发出信号。例如,通过调用WaitForSingleObject。显然,CreateProcess会返回一个您可以等待的进程句柄。你不能说服ShellExecute返回一个进程句柄,但它更有能力的兄弟ShellExecuteEx会这样做。

但是,我个人会在这里选择CreateProcess。您将获得更多的灵活性和控制力,而且并不复杂。例如,您可以根据需要禁止显示控制台窗口。

答案 2 :(得分:1)

好的,我已经对此进行了更多的研究并解决了它,就像大卫建议的那样。我会展示我的所作所为,如果其他人有任何问题或其他任何问题:

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;

完全符合我的要求。 2个sikuli脚本将一个接一个地运行。

答案 3 :(得分:0)

这是一种不太复杂的黑客攻击方式,但也许你可以生成一个* .bat文件,其中包含对脚本的调用,必要时在每一行使用“start / wait”。