CreateProcess,WaitForSingleObject,在调用应用程序上禁用输入

时间:2019-02-07 07:06:32

标签: delphi createprocess disabled-input

我正在调用另一个仅显示如下网页的程序:

问题:如果我使用按钮创建了一个流程,并且在“创建的流程”处于打开状态时,我单击了调用表单上的“复选框”,则我关闭了创建的流程,“复选框”被选中。

我尝试使用.ShowModal函数中所示的DisableTaskWindows(0)。但这并没有按我预期的那样工作。虽然确实禁用了表单。但是在启用它之后,似乎表单仍然在处理click事件。有点像它有消息队列之类的东西。

谁能告诉我我在这里做错了什么事?

procedure TForm1.Button1Click(Sender: TObject);
var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
  ProcessCreated : Boolean;
  CommandLine : string;
  WindowList: TTaskWindowList;
begin
  WindowList := DisableTaskWindows(0);
  CommandLine:='webmodule.exe';
  uniqueString(CommandLine);
  ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
  StartupInfo.cb := SizeOf(StartupInfo);
  ProcessCreated := CreateProcess(PChar(nil), PChar(CommandLine), nil, nil, false, 0, nil, nil, StartupInfo, ProcessInfo);
  if ProcessCreated then
    WaitForSingleObject(ProcessInfo.hProcess, INFINITE)
  else
    ShowMessage('Error : could not execute!');
  CloseHandle(ProcessInfo.hProcess);
  CloseHandle(ProcessInfo.hThread);
  EnableTaskWindows(WindowList);
end;

更新

不幸的是,我不确定一个人如何使用RegisterWaitForSingleObject函数...我尝试了此方法,但是没有用。我可能想念CallBack吗?但是我不知道如何使用它。

  if ProcessCreated then
  begin
//    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    while (RegisterWaitForSingleObject(ProcessInfo.hProcess,ProcessInfo.hProcess,nil,nil,INFINITE,0) = false) do
    begin
      Form1.Color:=RGB(random(255),random(255),random(255));
      Application.ProcessMessages;
    end;

    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
  end
  else
    ShowMessage('Error : could not execute!');

更新2:

我想我可能已经解决了,我删除了“启用禁用表单”功能。相反,我在执行流程后执行此操作。

  while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE or PM_NOYIELD) do;
  while PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE or PM_NOYIELD) do;

1 个答案:

答案 0 :(得分:4)

问题在于,您在等待生成的进程退出时正在阻止应用程序的主消息循环,因此,直到该进程结束,才允许您的应用程序处理用户输入。您需要让您的应用正常处理消息,不要阻止它们。如果在生成的进程正在运行时禁用窗体,则用户输入将自动为您丢弃。

尝试更多类似的方法:

procedure TForm1.Button1Click(Sender: TObject);
var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
  CommandLine : string;
begin
  CommandLine := 'webmodule.exe';
  UniqueString(CommandLine);
  ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
  StartupInfo.cb := SizeOf(StartupInfo);
  if not CreateProcess(PChar(nil), PChar(CommandLine), nil, nil, FALSE, 0, nil, nil, StartupInfo, ProcessInfo) then
  begin
    ShowMessage('Error : could not execute!');
    Exit;
  end;
  CloseHandle(ProcessInfo.hThread);
  Enabled := False;
  repeat
    case MsgWaitForMultipleObjects(1, ProcessInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT) of
      WAIT_OBJECT_0: Break;
      WAIT_OBJECT_0+1: Application.ProcessMessages;
    else
      begin
        ShowMessage('Error : could not wait!');
        Break;
      end;
    end;
  until False;
  CloseHandle(ProcessInfo.hProcess);
  Enabled := True;
end;

或者这个:

type
  TForm1 = class(ToFrm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    ...
  private
    hWaitObj, hWaitProcess: THandle;
    procedure WaitFinished;
    ...
  end;

... 

procedure WaitCallback(lpParameter: Pointer; WaitFired: Boolean); stdcall;
begin
  TThread.Queue(nil, TForm1(lpParameter).WaitFinished);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
  CommandLine : string;
begin
  CommandLine := 'webmodule.exe';
  UniqueString(CommandLine);
  ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
  StartupInfo.cb := SizeOf(StartupInfo);
  if not CreateProcess(PChar(nil), PChar(CommandLine), nil, nil, FALSE, 0, nil, nil, StartupInfo, ProcessInfo) then
  begin
    ShowMessage('Error : could not execute!');
    Exit;
  end;
  CloseHandle(ProcessInfo.hThread);
  if not RegisterWaitForSingleObject(hWaitObj, ProcessInfo.hProcess, WaitCallback, Self, INFINITE, WT_EXECUTELONGFUNCTION or WT_EXECUTEONLYONCE) then
  begin
    CloseHandle(ProcessInfo.hProcess);
    ShowMessage('Error : could not wait!');
    Exit;
  end;
  hWaitProcess := ProcessInfo.hProcess;
  Enabled := False;
end;

procedure TForm1.WaitFinished;
begin
  UnregisterWait(hWaitObj);
  CloseHandle(hWaitProcess);
  Enabled := True;
end;