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

=== Как запустить программу и подождать ее завершения? ===
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