Am 02.02.2012 12:00, schrieb [email protected]:
Hi, I need run 3 external program and redirected output: first | second | third
For example:
df -hT | grep -v -E 'tmpfs|ecryptfs' | grep 'sda2'
it gives
/dev/sda2 ext4 19G 11G 7,6G 58% /
I use this
http://wiki.lazarus.freepascal.org/Executing_External_Programs#How_to_redirect_output_with_TProcess
sample code. It works fine for first | second.
For three programs I try edit it:
function threePipe(inputA, inputB, inputC: string): string;
var
FirstProcess, SecondProcess, ThirdProcess: TProcess;
Buffer: array[0..127] of char;
ReadCount: Integer;
ReadSize: Integer;
begin
FirstProcess := TProcess.Create(nil);
SecondProcess := TProcess.Create(nil);
ThirdProcess := TProcess.Create(nil);
FirstProcess.Options := [poUsePipes];
SecondProcess.Options := [poUsePipes];
ThirdProcess.Options := [poUsePipes,poStderrToOutPut];
FirstProcess.CommandLine := inputA;
SecondProcess.CommandLine := inputB;
ThirdProcess.CommandLine := inputC;
FirstProcess.Execute;
SecondProcess.Execute;
ThirdProcess.Execute;
while FirstProcess.Running or (FirstProcess.Output.NumBytesAvailable> 0) do
begin
if FirstProcess.Output.NumBytesAvailable> 0 then
begin
ReadSize := FirstProcess.Output.NumBytesAvailable;
if ReadSize> SizeOf(Buffer) then
ReadSize := SizeOf(Buffer);
ReadCount := FirstProcess.Output.Read(Buffer[0], ReadSize);
SecondProcess.Input.Write(Buffer[0], ReadCount);
end;
end;
SecondProcess.CloseInput;
while SecondProcess.Running or (SecondProcess.Output.NumBytesAvailable> 0) do
begin
if SecondProcess.Output.NumBytesAvailable> 0 then
begin
ReadSize := SecondProcess.Output.NumBytesAvailable;
if ReadSize> SizeOf(Buffer) then
ReadSize := SizeOf(Buffer);
ReadCount := SecondProcess.Output.Read(Buffer[0], ReadSize);
ThirdProcess.Input.Write(Buffer[0], ReadCount);
end;
end;
ThirdProcess.CloseInput;
while ThirdProcess.Running do
Sleep(1);
ReadSize := ThirdProcess.Output.NumBytesAvailable;
if ReadSize> SizeOf(Buffer) then
ReadSize := SizeOf(Buffer);
if ReadSize> 0 then
begin
ReadCount := ThirdProcess.Output.Read(Buffer, ReadSize);
//WriteLn(Copy(Buffer,0, ReadCount));
end
else
WriteLn('grep did not find what we searched for. ',
ThirdProcess.ExitStatus);
FirstProcess.Free;
SecondProcess.Free;
ThirdProcess.Free;
threePipe := Copy(Buffer,0, ReadCount);
end;
But after i call
Label1.Caption:=threePipe('df -hT', 'grep -v -E ''tmpfs|ecryptfs''', 'grep
''sda2''');
function my application end with infinite loop.
Where I do an error?
You need to read from all three processes in one loop as they will block
if they've reached the limit of the output pipe. Try something like this
(pseudo code):
while FirstProcess.Running or SecondProcess.Running or
ThirdProcess.Running do begin
FromFirstToSecond;
FromSecondToThird;
FromThirdToOutput;
end;
FromThirdToOutput; // <= you need to process the leftover output from
the process as well
It might be more complex than the above, but in essence this should do
it (maybe you'll need to play with the buffer sizes, etc).
Regards,
Sven
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus