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

Reply via email to