Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Системные функции, WinAPI, работа с железом > Запуск программы с ожиданием её выполнения


Автор: Song 12.12.03, 08:09
Запустить процесс и дождаться его завершения

В приведённом ниже примере, не претендующем на панацею, используется запуск архиватора rar в отдельном процессе для архивирования/разархивирования целого каталога. После этого организуется цикл ожидания, до тех пор пока процесс не отработает. Обратите внимание, что используется альтернатива функции WaitForSingleObject(), собственная организация цикла. Хорошо это или плохо, решать вам.

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Procedure CrProcess(FileName, S, Dir, WindowName: String);
    // © 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;


Примеры использования:

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    // заархиировать
    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

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

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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;


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

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ExecAndWait( 'C:\windows\calc.exe', '', SH_SHOWNORMAL)


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

PS: Этот код тестировался в delphi версий 3, 4 и 5.

Тема - элемент ЧАВО. Подготовлена by © Song

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)