CreateProcess возвращается немедленно, но только если запущенный процесс скрыт - PullRequest
2 голосов
/ 04 ноября 2010

У меня есть приведенный ниже код Delphi, чтобы обеспечить дружественную оболочку для вызова API CreateProcess.

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;

Я использую его для запуска пакетного файла и жду, пока пакетный файл вернется.Это работает хорошо, пока я оставляю значение "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);

Странно, когда окно скрыто, я все равно получаю идентификатор процесса обратно, как если бы он начался.Но он выходит так быстро, что я не вижу его в диспетчере задач.

Если я изменю командный файл, чтобы в конце его была «пауза» (чтобы он никогда не закончился), явсе равно получаю тот же результат.Таким образом, кажется, что процесс действительно не запускается, когда я устанавливаю флаги в блоке «if not (ShowWindow)» моего кода.

После предложений Роба Кеннеди мой код выглядит так:

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;

1 Ответ

7 голосов
/ 04 ноября 2010

Когда вы устанавливаете ShowWindow = False, вы устанавливаете флажки запуска, включающие StartF_UseStdHandles, но вы никогда не предоставляете никаких значений для стандартных дескрипторов ввода / вывода. В тот момент, когда новый процесс попытается записать какой-либо вывод, он потерпит неудачу, поскольку у него нет действительного дескриптора вывода.

Если вы не собираетесь предоставлять значения для дескрипторов, не говорите CreateProcess, что в полях дескрипторов есть допустимые значения. Опустите этот флаг из флагов запуска.

Вы не получаете никакой ошибки при создании процесса, потому что создание процесс прошел нормально. Это только после процесс начал работать, что он столкнулся с проблемами. Вы не проверяете код завершения процесса, поэтому вы не сможете обнаружить какой-либо сбой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...