Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2026-01

Free Pascal / Free Vision: Executing shell commands and showing output

4 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Aruna Hewapathirane

Hello everyone, I’ve recently started exploring the Free Pascal source tree and digging into the fp text-mode IDE to better understand how things are structured and implemented. As a learning exercise, I put together a very simple Free Vision program that runs lsblk -S and displays the output in a scrollable TListBox.

The attached screenshot shows the issue I’m running into with the displayed output. I’m clearly missing something fundamental here, and I’d appreciate any pointers in the right direction.

Would this also be an appropriate question to raise on the fpc-devel list?

Thanks in advance.

Aruna Hewapathirane

Reply by email

Bart
to Aruna Hewapathirane
The attached screenshot shows the issue I’m running into with the displayed output. I’m clearly missing something fundamental here, and I’d appreciate any pointers in the right direction.

What happens if you output the Result to a file?

I use similar code (allbeit in a Lazarus program), I use
LoadFromStream(Proc.Output) instead of your CopyFrom(), not sure if
that matters.
===
type
  TBlockDeviceInfoStrings = type TStringList;
...
procedure GetBlockDeviceInfoStrings(BlockDeviceInfoStrings:
TBlockDeviceInfoStrings);
var
  Proc: TProcess;
  i: Integer;
begin
  BlockDeviceInfoStrings.Clear;
  Proc := TProcess.Create(nil);
  try
  Proc.Executable := 'lsblk';   //ToDo: get this from path  ??
  Proc.Parameters.Add('--pair'); //output in Key-Value pairs
  //Proc.Parameters.Add('-e7'); //exclude RAM drives
  Proc.Parameters.Add('-a');    //list all blockdevices
  Proc.Parameters.Add('-b');    //size in bytes
  Proc.Parameters.Add('-o');    //output
  Proc.Parameters.Add('NAME,MOUNTPOINT,LABEL,FSTYPE,TYPE,PARTTYPE,UUID,MODEL,TRAN,RM,SIZE,FSSIZE,FSUSED,FSUSE%,FSAVAIL');
 //output columns
  Proc.Options := Proc.Options + [poWaitOnExit, poUsePipes];
  Proc.Execute;
  //writeln('lsblk: Proc.ExitCode=',Proc.ExitCode,',
Proc.ExitStatus=',Proc.ExitStatus);
  if not (Proc.ExitCode = 0) and (Proc.ExitStatus = 0) then
  begin
    writeln(stderr,'lsblk: ExitCode=',Proc.ExitCode,',
ExitStatus=',Proc.ExitStatus);
    Exit;
  end;
  BlockDeviceInfoStrings.LoadFromStream(Proc.Output);
  for i := BlockDeviceInfoStrings.Count - 1 downto 0 do
    if (Trim(BlockDeviceInfoStrings[i])='') then
      BlockDeviceInfoStrings.Delete(i);
  finally
    Proc.Free;
  end;
end;
===
Bart

Reply by email

Michael Van Canneyt
to Bart
Bart wrote 11 lines
On Tue, Jan 27, 2026 at 9:44 AM Aruna Hewapathirane via fpc-devel wrote: > The attached screenshot shows the issue I’m running into with the displayed output. I’m clearly missing something fundamental here, and I’d appreciate any pointers in the right direction. What happens if you output the Result to a file? I use similar code (allbeit in a Lazarus program), I use LoadFromStream(Proc.Output) instead of your CopyFrom(), not sure if that matters.

It does.

1. Do not use CopyFrom on a non-seekable stream such as a pipe (which is used to capture output in TProcess). this is documented: https://www.freepascal.org/docs-html/rtl/classes/tstream.copyfrom.html

2. Do not use the poWaitOnExit flag. When the program you start outputs more data then the size of the OS pipe buffer then it will be blocked waiting for you to free the pipe buffer, while you wait for it to finish.

Instead, do a loop:

   ...
   Proc.Options := Proc.Options + [poUsePipes]-[poWaitOnExit];
   Proc.Execute;
   While Proc.Running do
     begin
     nBytesRead:=Proc.Output.Read(Buffer,SizeOf(Buffer);
     S.WriteBuffer(Buffer,BytesRead);
     end;
   // Read remaining
   nBytesRead:=proc.Output.Read(Buffer,SizeOf(Buffer);
   S.WriteBuffer(Buffer,BytesRead);
   // ...
   // Check exit status and further processing

Michael.

Reply by email

n7800
to Michael Van Canneyt
Show quoted text 11 lines
1. Do not use CopyFrom on a non-seekable stream such as a pipe (which is used to capture output in TProcess). this is documented: https://www.freepascal.org/docs-html/rtl/classes/tstream.copyfrom.html 2. Do not use the poWaitOnExit flag. When the program you start outputs more data then the size of the OS pipe buffer then it will be blocked waiting for you to free the pipe buffer, while you wait for it to finish.

I'll supplement the answer above with a link to a good article about this:

https://wiki.freepascal.org/Executing_External_Programs#Reading_large_output

Reply by email