执行并等待有时不起作用 [英] Execute and Wait not working sometimes

查看:89
本文介绍了执行并等待有时不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用在Internet上找到的这段代码,并且在某些设备上等待,但是在其他设备上则没有.有人可以解释我要去哪里了.我的应用程序在Truecrypt中加载,然后等待用户输入密码.退出Truecrypt后,它将启动我的菜单程序.

I am using this code I found on the Internet and on some devices it waits, but on others it does not. Can someone please explain where I am going wrong. My app loads in Truecrypt and then waits for the user to enter the password. On exiting Truecrypt, it then launches my menu-program.

我的Lenovo Miix 2 8平板电脑,win8.1(所有最新版本)将等待,我父亲的win8.0(所有文字,最新)将等待,但是我朋友的ASUS M80TA 8" win8.1平板电脑(全部(最新)).另一个朋友的win7笔记本电脑(都是最新的)不等待以太币.

My Lenovo Miix 2 8" tablet, win8.1 (all up to date) will wait, my Dad's win8.0 (all up to date) will wait, but my friend's ASUS M80TA 8" win8.1 tablet (all up to date) will not. Another friend's win7 laptop (all up to date) does not wait ether.

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. 您调用CreateProcess来创建一个新进程并返回该进程的句柄.
  2. 第一个新流程又开始一个不同的流程,并立即返回.第二个过程就是您看到的过程,并相信是您创建的过程.
  3. 您等待第一个进程句柄返回.

为了知道如何处理,您需要提供一些有关您尝试开始的过程的详细信息.至于为什么代码可以在某些机器上而不在其他机器上工作,则可能取决于目标应用程序(您正在启动的外部应用程序)的实现细节.大概因机器而异.

In order to know how to deal with this you'd need to supply some details about the process that you are attempting to start. As to why the code works on some machines and not others, that would likely be down to the implementation details of the target application, the external application that you are starting. Presumably it differs from machine to machine.

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

Looking at the code, it always leaks the thread handle returned in aTPI.hThread. And it leaks aTPI.hProcess if GetExitCodeProcess fails.

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

You also need to ensure that the string you pass to the command line argument of CreateProcess is an editable string, and not a literal that is stored in read-only memory.

初始化ExitCode然后立即覆盖它也是没有意义的.此外,您可以删除ExitCode变量并将Result直接传递给GetExitCodeProcess.

It is also pointless to initialise ExitCode and then immediately overwrite it. What's more you can remove the ExitCode variable and pass Result directly to GetExitCodeProcess.

您的代码也无法确认等待函数返回的错误.

Your code also fails to acknowledge an error being returned by the wait function.

我可能会这样写:

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'传递给此函数时,该函数在记事本进程关闭之前不会返回.

On my machine, when I pass 'notepad.exe' to this function, the function does not return until the Notepad process is closed.

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

On the other hand, if I pass 'explorer.exe' to the process, then the function returns immediately. What happens here is that a new explorer process starts, but it detects that one is already running, and asks that process to open a new window. The newly started explorer process immediately terminates.

这篇关于执行并等待有时不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆