I have the below Delphi code to provide a friendly wrapper for the CreateProcess API call.
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;
I am using it to start a batch file, and wait for the batch file to return. It works nicely as long as I leave the "ShowWindow" value as True. If I try to hide the command line window, then it returns immediately with no error. Can anyone help me understand my mistake here? Example usage is below with comments.
//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);
An odd thing is when the window is hidden, I still get a process ID back, as if it started. But it quits so fast that I can't see it in the task manager.
If I change the batch file to have a "pause" at the end of it (so it will never really finish), I still get the same result. So it appears that the process really does not start when I set the flags in the "if not(ShowWindow)" block of my code.
After Rob Kennedy's suggestions, my code looks like this:
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;
WaitForSingleObject(ProcInfo.hProcess, Infinite). - Rob Kennedy