Как запустить программу и подождать ее завершения?

Материал из DRKB

Как запустить программу и подождать ее завершения?[править | править код]

var
  pi: TProcessInformation;
  si: TStartupInfo;
begin
  ZeroMemory(@si, SizeOf(si));
  si.cb := SizeOf(si);
  if not CreateProcess(
    PChar(lpApplicationName), //pointer to name of executable module
    PChar(lpCommandLine), // Command line.
    nil, // Process handle not inheritable.
    nil, // Thread handle not inheritable.
    False, // Set handle inheritance to FALSE.
    0, // No creation flags.
    nil, // Use parent's environment block.
    nil, // Use parent's starting directory.
    si, // Pointer to STARTUPINFO structure.
    pi ) // Pointer to PROCESS_INFORMATION structure.
  then
  begin
    Result := False;
    RaiseLastWin32Error; 
    Exit;
  end;
  WaitForSingleObject(pi.hProcess, INFINITE);
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
  // ... здесь твой код
end;

Примечание Vit:

Если заменить

WaitForSingleObject(pi.hProcess, INFINITE);

на

while WaitforSingleObject(PI.hProcess, 200) = WAIT_TIMEOUT do
  Application.ProcessMessages;

то вызывающая программа не будет казаться завешанной и будет отвечать на сообщения


Примечание Mikel: В RxLib есть функция для этого: FileExecuteWait


Author: TAPAKAH
Source: Взято с Vingrad.ru http://forum.vingrad.ru
ID: 02064



Здесь представлена функция, которая вызывается таким же образом как и WinExec, однако она ждёт, пока запущенная задача завершится.

function WinExecAndWait(Path: PChar; Visibility: Word): Word; 
var 
  InstanceID: THandle; 
  Msg: TMsg; 
begin 
  InstanceID := WinExec(Path, Visibility); 
  if InstanceID < 32 then { значение меньше чем 32 указывает на ошибку }
    WinExecAndWait := InstanceID 
  else 
    repeat 
       while PeekMessage(Msg, 0, 0, 0, pm_Remove) do 
       begin 
         if Msg.Message = wm_Quit then Halt(Msg.WParam); 
         TranslateMessage(Msg); 
         DispatchMessage(Msg); 
       end; 
    until GetModuleUsage(InstanceID) = 0; 
  WinExecAndWait := 0; 
end;


Source: Взято из http://forum.sources.ru
ID: 02065



Пример показывает как из Вашей программы запустить внешнее приложение и подождать его завершения.


function ExecAndWait(const FileName, Params: ShortString; const WinState: Word): boolean; export; 
var 
  StartInfo: TStartupInfo; 
  ProcInfo: TProcessInformation; 
  CmdLine: ShortString; 
begin 
  { Помещаем имя файла между кавычками, с соблюдением всех пробелов в именах Win9x } 
  CmdLine := '"' + Filename + '" ' + Params; 
  FillChar(StartInfo, SizeOf(StartInfo), #0); 
  with StartInfo do 
  begin 
    cb := SizeOf(SUInfo); 
    dwFlags := STARTF_USESHOWWINDOW; 
    wShowWindow := WinState; 
  end; 
  Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false, 
                          CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, 
                          PChar(ExtractFilePath(Filename)), StartInfo, ProcInfo); 
  { Ожидаем завершения приложения } 
  if Result then 
  begin 
    WaitForSingleObject(ProcInfo.hProcess, INFINITE); 
    { Free the Handles } 
    CloseHandle(ProcInfo.hProcess); 
    CloseHandle(ProcInfo.hThread); 
  end; 
end;


А вот пример вызова этой функции:


ExecAndWait( 'C:\windows\calc.exe', , SH_SHOWNORMAL) 

  • Параметр FileName = Имя внешней программы.
  • Параметр Params = Параметры, необходимые для запуска внешней программы
  • Параметр WinState = Указывает - как будет показано окно. Для этого параметра мы можем так же использовать следующие константы:
    • SW_HIDE
    • SW_MAXIMIZE
    • SW_MINIMIZE
    • SW_SHOWNORMAL


Source: Взято из http://forum.sources.ru
ID: 02066