CreateProcess立即返回,但仅在隐藏已启动的进程时才返回

Jos*_*ons 2 delphi winapi

我有以下Delphi代码,为CreateProcess API调用提供友好的包装器.

function StartProcess(ExeName: string; CmdLineArgs: string = '';
  ShowWindow: boolean = True; WaitForFinish: boolean = False): integer;
const
  c_Wait = 100;
var
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
begin
  //Simple wrapper for the CreateProcess command
  //returns the process id of the started process.
  FillChar(StartInfo,SizeOf(TStartupInfo),#0);
  FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
  StartInfo.cb := SizeOf(TStartupInfo);

  //this block is the only part of execution that is different
  //between my two calls.  What am I doing wrong with these flags?
  if not(ShowWindow) then begin
    StartInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
    StartInfo.wShowWindow := SW_HIDE;
  end;

  CreateProcess(nil,PChar(ExeName + ' ' + CmdLineArgs),nil,nil,False,
    CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS,nil,nil,StartInfo,
    ProcInfo);

  Result := ProcInfo.dwProcessId;

  if WaitForFinish then begin
    while IsProcessRunning(Result) do begin
      Sleep(c_Wait);
    end;
  end;

end;
Run Code Online (Sandbox Code Playgroud)

我正在使用它来启动批处理文件,并等待批处理文件返回.只要我将"ShowWindow"值保留为True,它就可以很好地工作.如果我试图隐藏命令行窗口,它会立即返回,没有错误.任何人都可以帮我理解我的错误吗?示例用法如下,注释.

//this will not show the cmd line window, and it will return immediately
StartProcess('C:\run_me.bat','',False,True);

//this will show the cmd line, and (correctly) wait for the job to finish
StartProcess('C:\run_me.bat','',True,True);
Run Code Online (Sandbox Code Playgroud)

奇怪的是当窗口被隐藏时,我仍然得到一个进程ID,就像它开始一样.但它退出的速度如此之快,以至于我无法在任务管理器中看到它.

如果我将批处理文件更改为在其末尾有一个"暂停"(因此它永远不会真正完成),我仍然得到相同的结果.因此,当我在代码的"if not(ShowWindow)"块中设置标志时,似乎该进程确实没有启动.

在Rob Kennedy的建议之后,我的代码看起来像这样:

function StartProcess(ExeName: string; CmdLineArgs: string = '';
  ShowWindow: boolean = True; WaitForFinish: boolean = False): integer;
var
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
begin
  //Simple wrapper for the CreateProcess command
  //returns the process id of the started process.
  FillChar(StartInfo,SizeOf(TStartupInfo),#0);
  FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
  StartInfo.cb := SizeOf(TStartupInfo);

  if not(ShowWindow) then begin
    StartInfo.dwFlags := STARTF_USESHOWWINDOW;
    StartInfo.wShowWindow := SW_HIDE;
  end;

  CreateProcess(nil,PChar(ExeName + ' ' + CmdLineArgs),nil,nil,False,
    CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS,nil,nil,StartInfo,
    ProcInfo);

  Result := ProcInfo.dwProcessId;

  if WaitForFinish then begin
    WaitForSingleObject(ProcInfo.hProcess,Infinite);
  end;

  //close process & thread handles
  CloseHandle(ProcInfo.hProcess);
  CloseHandle(ProcInfo.hThread);
end;
Run Code Online (Sandbox Code Playgroud)

Rob*_*edy 7

设置时ShowWindow = False,将启动标志设置为include StartF_UseStdHandles,但是从不为标准I/O句柄提供任何值.新进程尝试写入任何输出的那一刻,它将失败,因为它没有有效的输出句柄.

如果您不打算为句柄提供值,则不要告诉CreateProcess句柄字段中包含有效值.从启动标志中省略该标志.

创建过程时不会出现任何错误,因为创建过程很顺利.只有流程开始运行才会遇到问题.您没有检查进程的退出代码,因此您无法检测到任何故障.