Запуск программы с ожиданием её выполнения
Запуск программы с ожиданием её выполнения
Запуск программы с ожиданием её выполнения В приведённом ниже примере, не претендующем на панацею, используется запуск архиватора rar в отдельном процессе для архивирования/разархивирования целого каталога. После этого организуется цикл ожидания, до тех пор пока процесс не отработает. Обратите внимание, что используется альтернатива функции WaitForSingleObject(), собственная организация цикла. Хорошо это или плохо, решать вам. Procedure CrProcess(FileName, S, Dir, WindowName: String); // c Song Var SeInfo: TShellExecuteInfo; ExitCode: DWord; Begin FillChar(SEInfo,SizeOf(SEInfo),0); With SEInfo Do Begin cbSize:=SizeOf(TShellExecuteInfo); fmask:=SEE_MASK_NOCLOSEPROCESS; Wnd:=Application.Handle; lpFile:=PChar('"'+FileName+'"'); lpParameters:=PChar(S); lpDirectory:=nil; { Можете использовать другие константы, если хотите, чтобы выполнение процесса было видно } nShow:=SW_HIDE; End; {With} IF ShellExecuteEx(@SEInfo) then Repeat Application.ProcessMessages; GetExitCodeProcess(SEInfo.hProcess,ExitCode); Until(FindWindow(nil,PChar(WindowName))<>0) or (ExitCode<>STILL_ACTIVE) or Application.Terminated else MessageDlg('Ошибка создания внешнего процесса. Код ошибки: '+SysErrorMessage(GetLastError),mtError,[mbAbort],0); CloseHandle(SEInfo.hProcess); IF FindWindow(nil,PChar(WindowName))<>0 then Begin SendMessage(FindWindow(nil,PChar(WindowName)),WM_CLOSE,0,0); While FindWindow(nil,PChar(WindowName))<>0 Do Application.ProcessMessages; End; {IF} End; Примеры использования: // заархиировать CrProcess('путь_к_архиваору_rar','a -r0 -m5 '+'имя_архива'+#32+'имя_каталога'+'*.*',TempPath,'(Сеанс завершен) - Rar'); // разархивировать CrProcess('путь_к_архиваору_rar','x -y '+'имя_архива'+#32+'каталог_куда_разархивировать','(Сеанс завершен) - Rar'); Процедура написана исходя из совместимости со старыми ДОС процессами. ДОС программы не оставляют код завершения своего процесса по коду STILL_ACTIVE, а поэтому в таком случае запуск процесса "повиснет", т.е. будет постоянно "крутится" в цикле Repeat .. Until(). Для таких случаев преднозначена переменная WindowName. Когда ДОС задача завершается, появляется окно "(Сеанс завершён) - Имя_процесса". Используйте эту переменную, если вы запускаете ДОС программу, вписав при этом в эту переменную свою строку по аналогии. В этом случае цикл Repeat .. Until() оборвётся при наличии такого окна, т.е. когда процесс и завершится. До кучи ещё процедура закроет это окно, чтобы предотвратить проблему при многократных запусках. Вариант №2 через WaitForSingleObject Автор: Fabrнcio Fadel Kammer Пример показывает как из Вашей программы запустить внешнее приложение и подождать его завершения. 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(StartInfo); 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