Как заблокировать поток VCL при запуске функции, подобной shellexecute - PullRequest
0 голосов
/ 08 февраля 2020

Извиняюсь за неправильную терминологию при обращении к структуре VCL / основного потока Delphi (если у кого-то есть какие-либо ресурсы, чтобы узнать больше об этом, я был бы признателен).

По сути, у меня есть приложение VCL, где при событии нажатия кнопки я хочу, чтобы пользователь не мог взаимодействовать с исходным приложением VCL, которое порождает внешний exe-файл.

У меня есть функция с именем ExecuteExternalProcess, которая при передаче соответствующих параметров не разрешит следующее строка (и) кода для выполнения, пока внешнее приложение не вернуло значение. Это хорошо работает в других приложениях, но не так сильно, когда мы порождаем внешний exe из события VCL.

Вот событие Button Click, которое порождает внешний процесс

procedure TMainForm.ButtonBtnClick(Sender: TObject);
var
 error: Integer;
begin
 ExecuteExternalProcess('test.exe', '', '', True, false, false, error);
 showmessage('done');
end;

это работает, оно не отображает сообщение «сделано», пока не завершится выполнение test.exe. Повторим еще раз: проблема в том, что во время работы test.exe я могу взаимодействовать с исходным приложением VCL и делать что угодно. Я хотел бы, чтобы начальное приложение VCL полностью остановилось и было неработоспособным, пока не завершится выполнение test.exe.

Вот код, который порождает исполняемый файл, если он помогает (я не автор, от которого я получил его) здесь):

function ExecuteExternalProcess(const FileName, Params: string; Folder: string; WaitUntilTerminated, WaitUntilIdle, RunMinimized: boolean;
  var ErrorCode: integer): boolean;
var
  CmdLine: string;
  WorkingDirP: PChar;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  Result := true;
  CmdLine := '"' + FileName + '" ' + Params;
  //if Folder = '' then Folder := ExcludeTrailingPathDelimiter(ExtractFilePath(FileName));
  ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
  StartupInfo.cb := SizeOf(StartupInfo);
  if RunMinimized then
    begin
      StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
      StartupInfo.wShowWindow := SW_SHOWMINIMIZED;
    end;
  if Folder <> '' then WorkingDirP := PChar(Folder)
  else WorkingDirP := nil;
  if not CreateProcess(nil, PChar(CmdLine), nil, nil, false, 0, nil, WorkingDirP, StartupInfo, ProcessInfo) then
    begin
      Result := false;
      ErrorCode := GetLastError;
      exit;
    end;
  with ProcessInfo do
    begin
      CloseHandle(hThread);
      if WaitUntilIdle then WaitForInputIdle(hProcess, INFINITE);
      if WaitUntilTerminated then
        repeat
          Application.ProcessMessages;
        until MsgWaitForMultipleObjects(1, hProcess, false, INFINITE, QS_ALLINPUT) <> WAIT_OBJECT_0 + 1;
      CloseHandle(hProcess);
    end;
end;

1 Ответ

0 голосов
/ 08 февраля 2020

Почему бы просто не отключить tmainform.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...