I'm familiarizing myself with TProcess, so I decided to write a simple routine which executes a command and puts STDOUT/STDERR in a stringlist:
------------------------- procedure ExecCommand(const command : string; const stdout : TStringList; const stderr : TStringList; const timeoutSec : integer; out exitStatus : integer); const READ_BYTES = 2048; var P: TProcess; nOut : LongInt; nErr : LongInt; StdOutput : TMemoryStream; StdOutBytesRead: LongInt; StdError : TMemoryStream; StdErrBytesRead: LongInt; startTime : TDateTime; begin exitStatus := -1; StdOutput := TMemoryStream.Create; StdError := TMemoryStream.Create; StdOutBytesRead := 0; StdErrBytesRead := 0; try P := TProcess.Create(nil); try P.CommandLine := command; P.Options := [poUsePipes]; startTime := now; P.Execute; { read stderr and stdout while the process runs } while P.Running do begin StdOutput.SetSize(StdOutBytesRead + READ_BYTES); StdError.SetSize(StdErrBytesRead + READ_BYTES); nOut := P.Output.Read((StdOutput.Memory + StdOutBytesRead)^, READ_BYTES); if nOut > 0 then begin Inc(StdOutBytesRead, nOut); end; nErr := P.Stderr.Read((StdError.Memory + StdErrBytesRead)^, READ_BYTES); if nErr > 0 then begin Inc(StdErrBytesRead, nErr); end; if (nErr = 0) and (nOut = 0) then Sleep(100); if (timeoutSec > 0) and (SecondsBetween(now, startTime) > timeoutSec) then begin P.Terminate(exitStatus); raise Exception.Create('Execution timed out'); end; end; exitStatus := P.ExitStatus; { read what's left over in stdout } repeat StdOutput.SetSize(StdOutBytesRead + READ_BYTES); nOut := P.Output.Read((StdOutput.Memory + StdOutBytesRead)^, READ_BYTES); if nOut > 0 then begin Inc(StdOutBytesRead, nOut); end; until nOut <= 0; { read what's left over in stderr } repeat StdError.SetSize(StdErrBytesRead + READ_BYTES); nErr := P.Stderr.Read((StdError.Memory + StdErrBytesRead)^, READ_BYTES); if nErr > 0 then begin Inc(StdErrBytesRead, nErr); end; until nErr <= 0; StdOutput.SetSize(StdOutBytesRead); if Assigned(stdout) then begin stdout.LoadFromStream(StdOutput); end; StdError.SetSize(StdErrBytesRead); if Assigned(stderr) then begin stderr.LoadFromStream(StdError); end; finally FreeAndNil(StdOutput); FreeAndNil(StdError); FreeAndNil(P); end; except on E : Exception do begin exitStatus := -1; if Assigned(stderr) then begin stderr.Add(E.Message); end; end; end; end; ------------------------- Everything works fine unless the output to STDOUT of the command exceeds 65K (I'm testing it by running "cat /path/to/some/file" as the command). When this happens, the P.Stderr.Read inside the while loop just hangs and never returns. What am I doing wrong? -SG ======================== Computer over. Virus = very yes. Seth Grover sethdgrover[at]gmail[dot]com _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal