执行并等待有时不工作

时间:2014-10-03 14:48:17

标签: delphi wait execute

我正在使用我在互联网上找到的代码以及它等待的某些设备,但在其他设备上却没有。有人可以解释我哪里出错了。我的应用程序在Truecrypt中加载,然后等待用户输入密码。退出Truecrypt后,它会启动我的菜单程序。

我的联想Miix 2 8"平板电脑,win8.1(全部都是最新的)将等待,我父亲的win8.0(全部是最新的)将等待,但我的朋友的华硕M80TA 8" win8.1平板电脑(全部都是最新的)不会。另一位朋友的win7笔记本电脑(全部都是最新的)不等待以太。

var
  aTSI : TStartupInfo;
  aTPI : TProcessInformation;
  iRet : Integer;
  ExitCode: Cardinal;
begin
  FillChar(aTSI, SizeOf(aTSI), #0);
  FillChar(aTPI, SizeOf(aTPI), #0);
  aTSI.CB:=SizeOf(aTSI);
  if not CreateProcess(nil, PChar(sEXE), nil, nil, False,
                       NORMAL_PRIORITY_CLASS,
                       nil, nil, aTSI, aTPI) then
    RaiseLastWin32Error;
  repeat
    iRet:=MsgWaitForMultipleObjects(1, aTPI.hProcess,
    False, INFINITE, (QS_ALLINPUT));
    if iRet <> (WAIT_OBJECT_0) then
      Application.ProcessMessages;
  until iRet = (WAIT_OBJECT_0); // use this for normal programs
  ExitCode:= 0;
  if not GetExitCodeProcess(aTPI.hProcess, ExitCode) then
    RaiseLastWin32Error;
  Result:= ExitCode;
  CloseHandle(aTPI.hProcess);
end;

1 个答案:

答案 0 :(得分:0)

可能的解释如下:

  1. 您调用CreateProcess,它创建一个新进程并返回该进程的句柄。
  2. 第一个新流程又会启动一个不同的流程,并立即返回。第二个流程是您看到的流程,并且相信您创建的流程。
  3. 您对第一个进程句柄的等待返回。
  4. 为了了解如何处理此问题,您需要提供有关您尝试启动的流程的一些详细信息。至于为什么代码在某些机器而不是其他机器上工作,这可能取决于目标应用程序的实现细节,即您正在启动的外部应用程序。据推测,它因机器而异。

    查看代码,它总是泄漏aTPI.hThread中返回的线程句柄。如果aTPI.hProcess失败,它会泄漏GetExitCodeProcess

    您还需要确保传递给CreateProcess命令行参数的字符串是可编辑的字符串,而不是存储在只读存储器中的文字。

    初始化ExitCode然后立即覆盖它也毫无意义。您还可以删除ExitCode变量并将Result直接传递给GetExitCodeProcess

    您的代码也无法确认wait函数返回错误。

    我可能会这样写:

    function ExecAndWait(CommandLine: string): DWORD;
    var
      si: TStartupInfo;
      pi: TProcessInformation;
      iRet: Integer;
    begin
      UniqueString(CommandLine);
      si := Default(TStartupInfo);
      si.cb := SizeOf(si);
      Win32Check(CreateProcess(nil, PChar(CommandLine), nil, nil, False, 
        NORMAL_PRIORITY_CLASS, nil, nil, si, pi));
      CloseHandle(pi.hThread);
      try
        while True do
        begin
          iRet := MsgWaitForMultipleObjects(1, pi.hProcess, False, INFINITE, QS_ALLINPUT);
          Win32Check(iRet <> WAIT_FAILED);
          case iRet of
          WAIT_OBJECT_0:
            break;
          WAIT_OBJECT_0+1:
            Application.ProcessMessages;
          end;
        end;
        Win32Check(GetExitCodeProcess(pi.hProcess, Result));
      finally
        CloseHandle(pi.hProcess);
      end;
    end;
    

    在我的机器上,当我将'notepad.exe'传递给此函数时,在记事本进程关闭之前,该函数不会返回。

    另一方面,如果我将'explorer.exe'传递给进程,则函数立即返回。这里发生的是新的资源管理器进程启动,但它检测到一个已经在运行,并要求该进程打开一个新窗口。新启动的资源管理器进程会立即终止。