Страницы

Поиск по вопросам

понедельник, 30 марта 2020 г.

Как избежать подвисания программы во время ожидания выполнения другой через CreateProcess?

#delphi #winapi


Запускаю программу Delphi, открывается форма, нажимаю на кнопку, происходит выполнение
команды через cmd.exe. Мне нужно дождаться завершения ее выполнения. И пока команда
не выполниться - у меня сама форма (программа) Delphi находится в замороженном состоянии.
Мне нужно, чтобы сама форма (программа) Delphi - не была в замороженном состоянии.
То есть её можно было передвигать. Как сделать, чтобы окно программы Delphi в процессе
выполнения CMD.exe не застывало? То есть обработка в отдельном потоке.

var
  LCmd: string;
  LInfo: TStartupInfo;
  LPI: TProcessInformation;
begin
  // Заполняем структуры
  LCmd := 'cmd.exe ' + SPar;
  FillChar(LInfo, SizeOf(LInfo), 0);
  LInfo.cb := SizeOf(LInfo);
  LInfo.dwFlags := STARTF_USESHOWWINDOW;
  LInfo.wShowWindow := SW_HIDE;
  // Запускаем программу
  Win32Check(CreateProcess(
    'cmd.exe',        // lpApplicationName,
    PChar(LCmd),      // lpCommandLine,
    nil,              // lpProcessAttributes,
    nil,              // lpThreadAttributes,
    False,            // bInheritHandles,
    CREATE_NO_WINDOW, // dwCreationFlags,
    nil,              // lpEnvironment,
    nil,              // lpCurrentDirectory,
    LInfo,            // lpStartupInfo,
    LPI               // lpProcessInformation
  ));
  try
    // Закрываем хендл главного потока (он нам не нужен)
    CloseHandle(LPI.hThread);
    // Ждем завершения процесса
    Win32Check(WaitForSingleObject(LPI.hProcess, INFINITE) <> WAIT_FAILED);
  finally
    // Закрываем хендл процесса
    CloseHandle(LPI.hProcess);
  end;
  ShowMessage('Программа завершена');
end;

    


Ответы

Ответ 1



Чтобы дождаться завершения программы не замораживая интерфейс, нужно делать ожидание в отдельном потоке. А потом уведомить основной поток о завершении операции type TWaitThread = class(TThread) private FWaitHandle: THandle; protected procedure Execute; override; public constructor Create(ACreateSuspended: Boolean; AWaitHandle: THandle); destructor Destroy; override; end; constructor TWaitThread.Create(ACreateSuspended: Boolean; AWaitHandle: THandle); begin inherited Create(ACreateSuspended); FWaitHandle := AWaitHandle; end; destructor TWaitThread.Destroy; begin CloseHandle(FWaitHandle); inherited Destroy; end; procedure TWaitThread.Execute; begin // Ждем завершения процессса Win32Check(WaitForSingleObject(FWaitHandle, INFINITE) <> WAIT_FAILED); end; // И использование var .......... LPI: TProcessInformation; LThread: TThread; begin .......... Win32Check(CreateProcess(......, LPI)); CloseHandle(LPI.hThread); // Создаем ждущий поток LThread := TWaitThread.Create(True, LPI.hProcess); // Поток удалится при завершении LThread.FreeOnTerminate := True; // После завершения вызвать процедуру EndWait LThread.OnTerminate := EndWait; // Запускаем поток LThread.Start; end; procedure TForm1.EndWait(Sender: TObject); begin ShowMessage('Программа завершена'); end;

Комментариев нет:

Отправить комментарий