Multithreading 如何在等待子进程退出时暂停对我的应用程序的输入?

Multithreading 如何在等待子进程退出时暂停对我的应用程序的输入?,multithreading,delphi,shellexecuteex,Multithreading,Delphi,Shellexecuteex,我有一个函数,它允许我启动一个子进程,等待它终止,然后返回一个退出代码。子进程是Windows Installer,它安装一个MSI包,只显示其安装的当前进度。此函数是从后台线程中调用的 我将此函数包装为: function ShellExec(const Verb, Cmd, Params, Dir: WideString; const Visible: Bool): Integer; var FN: String; SEInfo: TShellExecuteInfo; Exi

我有一个函数,它允许我启动一个子进程,等待它终止,然后返回一个退出代码。子进程是Windows Installer,它安装一个MSI包,只显示其安装的当前进度。此函数是从后台线程中调用的

我将此函数包装为:

function ShellExec(const Verb, Cmd, Params, Dir: WideString;
  const Visible: Bool): Integer;
var
  FN: String;
  SEInfo: TShellExecuteInfo;
  ExitCode: DWORD;
begin
  Result:= 1;
  FillChar(SEInfo, SizeOf(SEInfo), 0);
  SEInfo.cbSize := SizeOf(TShellExecuteInfo);
  with SEInfo do begin
    fMask := SEE_MASK_NOCLOSEPROCESS;
    Wnd := Application.Handle;
    lpFile := PChar(Cmd);
    lpParameters := PChar(Params);
    lpDirectory := PChar(Dir);
    if Visible then
      nShow := SW_SHOWNORMAL
    else
      nShow := SW_HIDE;
  end;
  if ShellExecuteEx(@SEInfo) then begin
    repeat
      GetExitCodeProcess(SEInfo.hProcess, ExitCode);
    until (ExitCode <> STILL_ACTIVE) or
      Application.Terminated;
  end else begin
    ExitCode:= 1;
  end;
  Result:= ExitCode;
end;
这工作正常,但是它不会暂停我的呼叫应用程序的输入-用户仍然可以单击我的应用程序,尽管上面的函数中有循环-然后我的应用程序进入子进程的顶部。我需要子流程保持在我的应用程序顶部

该进程从主窗体后面的工作线程中启动。线程使用事件通知主窗体其进度。主窗体有两个动画,我仍然想继续,但我不希望用户能够在这个子应用仍在运行时单击该应用。我希望它看起来像模态状态。基本上,MSI进度应该始终位于我的应用程序之上


如何运行此子进程并防止用户返回主应用程序,以及防止主应用程序位于子应用程序之上?这是在Inno安装程序中执行相同操作时的默认行为,但我不知道如何在Delphi应用程序中执行此操作。

您真的要这样做吗?例如,如果用户试图关闭程序,而输入被禁用,会发生什么情况?您无法阻止应用程序进入前台,例如,通过禁用表单来阻止用户按下任务栏按钮。我认为,唯一可行的办法是改变窗口的所有权。不推荐,杂乱无章,一段时间以来甚至没有记录。为了更好的用户体验,IMHO,禁用您必须禁用的内容,关闭,按下按钮。。。但是让用户能够移动,最小化你的应用程序。你为什么要运行一个繁忙的循环?@Jerrydoge:这意味着它还可以响应用户交互、窗口激活/停用通知、z顺序更改等
function InstallNodeJs(const Config: TInstConfig): Integer;
var
  FN: String;
  Params: string;
begin
  Result:= 1;
  if Config.Is64 then
    FN := 'NodeInstall_x64.msi'
  else
    FN := 'NodeInstall_x86.msi';
  FN:= Config.TmpDir + FN;
  Params:= '/i "'+FN+'" /norestart /passive';
  Result:= ShellExec('', 'msiexec.exe', Params, '', True);
end;