Recent

Author Topic: [SOLVED] Output from TProcess breaks lines over 80 characters  (Read 10885 times)

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Output from TProcess breaks lines over 80 characters
« Reply #15 on: July 24, 2018, 06:41:06 am »
hello,
I have managed to use TProcess to run a command-line tool and output all messages in a component in my application.

you have better than TProcess to do that :  TProcessEx in the unit ProcessUtils of fpcUpDeluxe project.
TprocessEx includes Real time output management.
Example under linux to have the output of my biglines executable in realtime in a Tmemo :
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics,
  9.   Dialogs, StdCtrls, LazUtf8, Processutils;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     BtGo: TButton;
  17.     MemConsole: TMemo;
  18.     procedure BtGoClick(Sender: TObject);
  19.   private
  20.  
  21.   public
  22.     procedure ProcessOutput(Sender:TProcessEx; output:string);
  23.     procedure ProcessError(Sender:TProcessEx; {%H-}IsException:boolean);
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. implementation
  30.  
  31. {$R *.lfm}
  32.  
  33. { TForm1 }
  34.  
  35. procedure TForm1.BtGoClick(Sender: TObject);
  36. var Proc: TProcessEx;
  37. begin
  38.    try
  39.    Proc := TProcessEx.Create(nil);
  40.    Proc.Executable := '/home/jurassic/Lazarus/projets/biglines_output/biglines';
  41.    Proc.OnErrorM:=@(ProcessError);
  42.    Proc.OnOutputM:=@(ProcessOutput);
  43.    Proc.Execute();
  44.    finally
  45.      Proc.Free;
  46.    end;
  47. end;
  48.  
  49. procedure TForm1.ProcessError(Sender: TProcessEx; IsException: boolean);
  50. begin
  51.    MemConsole.Lines.Append('Erreur ! ' + Sender.ExceptionInfo);
  52. end;
  53.  
  54. procedure TForm1.ProcessOutput(Sender: TProcessEx; output : String);
  55. begin
  56.  MemConsole.Lines.Text :=  MemConsole.Lines.Text + output;
  57.   // si vous avez des problème d'accent
  58.   //MemConsole.Lines.Text := MemConsole.Lines.Text + ConsoleToUtf8(output);
  59.   // pour scroll automatique
  60.   MemConsole.SelStart := Length(MemConsole.Lines.Text)-1;
  61.   MemConsole.SelLength:=0;
  62. end;
  63.  
  64. end.
the biglines executable writes two lines of 120 characters :
Code: Pascal  [Select][+][-]
  1. program biglines;
  2. var myline : String;
  3. begin
  4. myline := StringofChar('a',120);
  5. writeln(myline);
  6. myline := StringofChar('b',120);
  7. writeln(myline);
  8. end.

The result  under Lubuntu 16.04  Lazarus 1.8.2 is in attachment. The lines with 120 characters are correctly displayed.
The project is in attachment. Processutils.pas coming from fpcUpDeluxe project has a MIT or LGPL licence.

Friendly, J.P

« Last Edit: July 24, 2018, 06:44:33 am by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

Leledumbo

  • Hero Member
  • *****
  • Posts: 8746
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Output from TProcess breaks lines over 80 characters
« Reply #16 on: July 24, 2018, 07:45:19 am »
I did check the whole string (the content of ReadBuffer) by outputting character by character - I wrote '(cr)' for character code 13 and '(lf)' for character code 10. So, I can confirm that a LF is already added at this point (before the string is added to TMemo).
Right, so it's the called program that does the line break. Gotta modify that one.

guest62822

  • Guest
Re: Output from TProcess breaks lines over 80 characters
« Reply #17 on: July 24, 2018, 11:59:29 am »
Quote
you have better than TProcess to do that :  TProcessEx in the unit ProcessUtils of fpcUpDeluxe project.
TprocessEx includes Real time output management.
Example under linux to have the output of my biglines executable in realtime in a Tmemo :

Great, I will have a look into that.

Quote
Right, so it's the called program that does the line break. Gotta modify that one.

The command-line program is a program written in Pascal (compiled with FPC) and I use Writeln to output messages. I haven't added anything on my own to break lines over 80 characters.

As 440bx said, it's almost like the program was run in a 80 character wide console (or terminal), and that's why the lines gets cut off. Many terminals in Linux has a character width of 80 by default as well.

But my current solution is, I have made a few changes and try to make sure that lines doesn't exceed 80 characters.

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: Output from TProcess breaks lines over 80 characters
« Reply #18 on: July 24, 2018, 12:16:15 pm »
As 440bx said, it's almost like the program was run in a 80 character wide console (or terminal), and that's why the lines gets cut off. Many terminals in Linux has a character width of 80 by default as well.

But my current solution is, I have made a few changes and try to make sure that lines doesn't exceed 80 characters.

I've often run into the problem of having lines longer than 80 characters wrap around.  As I mentioned previously, one solution is to programmatically control the width of the terminal/console.  The disadvantage of that solution is that your program has to know beforehand what the longest line is going to be (or make a guess).  The other solution, which IMO is a better one is, to always redirect the output to a file, that way there won't be any wrapping around no matter how long the longest line is.    Once the output is in a file, you can have your own way of displaying what is in it with full control over how each line is formatted.  Basically, you implement a simple file viewer that does horizontal scrolling if necessary.

Another advantage of the second solution is that it is a LOT faster to write to a file than to the console/terminal and there is no guessing about the length of the longest line.

Of course, changing the program to ensure its lines are less than 80 characters is nice.





(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Output from TProcess breaks lines over 80 characters
« Reply #19 on: July 24, 2018, 12:22:31 pm »
It would be better if you upload a minimal test project, that reproduces a possible bug, so we can test it.
You said you are linux user, but I cannot reproduce your case on linux.
Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

guest62822

  • Guest
Re: Output from TProcess breaks lines over 80 characters
« Reply #20 on: July 24, 2018, 12:30:15 pm »
Quote
As I mentioned previously, one solution is to programmatically control the width of the terminal/console.

TProcess has the property WindowColumns, but it's for Windows only. So, I'm not sure if there is other ways to control this.

Quote
Of course, changing the program to ensure its lines are less than 80 characters is nice.

Yes, it works quite well.

guest62822

  • Guest
Re: Output from TProcess breaks lines over 80 characters
« Reply #21 on: July 26, 2018, 03:59:26 pm »
Just an update:

I tried to run my application in Windows 7.

The command-line tool run as expected when running it directly from the DOS prompt.

However, when starting it from the main application (using TProcess), the DOS prompt shows up and it's completely empty - which also means that no output has been generated (no ReadBuffer --> empty TMemo).

It's the same code, so no clue why it doesn't work in Windows, or if it's a Windows thing to not show output in console in some cases.

M+AUDIO

  • New Member
  • *
  • Posts: 48
Re: Output from TProcess breaks lines over 80 characters
« Reply #22 on: July 26, 2018, 04:16:43 pm »
when starting it from the main application (using TProcess), the DOS prompt shows up and it's completely empty
Try and see if this helps:
Code: Pascal  [Select][+][-]
  1.     RunProcess.Options := [poUsePipes,poNoConsole];
  2.  

guest62822

  • Guest
Re: Output from TProcess breaks lines over 80 characters
« Reply #23 on: July 26, 2018, 04:32:36 pm »
when starting it from the main application (using TProcess), the DOS prompt shows up and it's completely empty
Try and see if this helps:
Code: Pascal  [Select][+][-]
  1.     RunProcess.Options := [poUsePipes,poNoConsole];
  2.  

I tried it - it stops the console to appear, but still no output.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Output from TProcess breaks lines over 80 characters
« Reply #24 on: July 27, 2018, 01:40:37 am »
hello,
with TprocessEx it still works under windows
Code: Pascal  [Select][+][-]
  1. procedure TForm1.BtGoClick(Sender: TObject);
  2. var Proc: TProcessEx;
  3. begin
  4.    try
  5.    Proc := TProcessEx.Create(nil);
  6.    Proc.Executable :='biglines.exe';    
  7.    Proc.OnErrorM:=@(ProcessError);
  8.    Proc.OnOutputM:=@(ProcessOutput);
  9.    Proc.Execute();
  10.    finally
  11.      Proc.Free;
  12.    end;
  13. end;          

Friendly, J.P
« Last Edit: July 27, 2018, 01:52:42 am by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

guest62822

  • Guest
Re: Output from TProcess breaks lines over 80 characters
« Reply #25 on: July 27, 2018, 02:04:00 pm »
hello,
with TprocessEx it still works under windows

Friendly, J.P

I tried ProcessEx - I had to rewrite some code, but sadly, I got exactly the same results.

I will see if I can find a fix or maybe go for a different solution (maybe skip processes and integrate the command-line tool into the main application and run it as a thread).

guest62822

  • Guest
Re: Output from TProcess breaks lines over 80 characters
« Reply #26 on: July 28, 2018, 11:22:39 am »
I finally solved it!

It was the command-line tool (or child process) that didn't work as expected in Windows.

Like I said earlier, the program worked fine when running it directly in the DOS prompt, but for some reason didn't generate any output (in Windows only) when running it from the main application using TProcess(Ex).


The changes I made to the command-line tool was:

1) I added a missing
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}

2) I replaced "Crt" with "Classes". (no clue what I used "Crt" for in the past)
Code: Pascal  [Select][+][-]
  1. uses
  2.   Classes, ...

I have no clue how this fixed the output, but now it works.

In Windows, I don't get any lines cut off after 80 characters, so I assume that's a Linux thing.

tatamata

  • Hero Member
  • *****
  • Posts: 787
    • ZMSQL - SQL enhanced in-memory database
Re: Output from TProcess breaks lines over 80 characters
« Reply #27 on: March 15, 2021, 08:16:54 pm »
hello,
I have managed to use TProcess to run a command-line tool and output all messages in a component in my application.

you have better than TProcess to do that :  TProcessEx in the unit ProcessUtils of fpcUpDeluxe project.
TprocessEx includes Real time output management.
Example under linux to have the output of my biglines executable in realtime in a Tmemo :
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics,
  9.   Dialogs, StdCtrls, LazUtf8, Processutils;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     BtGo: TButton;
  17.     MemConsole: TMemo;
  18.     procedure BtGoClick(Sender: TObject);
  19.   private
  20.  
  21.   public
  22.     procedure ProcessOutput(Sender:TProcessEx; output:string);
  23.     procedure ProcessError(Sender:TProcessEx; {%H-}IsException:boolean);
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29. implementation
  30.  
  31. {$R *.lfm}
  32.  
  33. { TForm1 }
  34.  
  35. procedure TForm1.BtGoClick(Sender: TObject);
  36. var Proc: TProcessEx;
  37. begin
  38.    try
  39.    Proc := TProcessEx.Create(nil);
  40.    Proc.Executable := '/home/jurassic/Lazarus/projets/biglines_output/biglines';
  41.    Proc.OnErrorM:=@(ProcessError);
  42.    Proc.OnOutputM:=@(ProcessOutput);
  43.    Proc.Execute();
  44.    finally
  45.      Proc.Free;
  46.    end;
  47. end;
  48.  
  49. procedure TForm1.ProcessError(Sender: TProcessEx; IsException: boolean);
  50. begin
  51.    MemConsole.Lines.Append('Erreur ! ' + Sender.ExceptionInfo);
  52. end;
  53.  
  54. procedure TForm1.ProcessOutput(Sender: TProcessEx; output : String);
  55. begin
  56.  MemConsole.Lines.Text :=  MemConsole.Lines.Text + output;
  57.   // si vous avez des problème d'accent
  58.   //MemConsole.Lines.Text := MemConsole.Lines.Text + ConsoleToUtf8(output);
  59.   // pour scroll automatique
  60.   MemConsole.SelStart := Length(MemConsole.Lines.Text)-1;
  61.   MemConsole.SelLength:=0;
  62. end;
  63.  
  64. end.
the biglines executable writes two lines of 120 characters :
Code: Pascal  [Select][+][-]
  1. program biglines;
  2. var myline : String;
  3. begin
  4. myline := StringofChar('a',120);
  5. writeln(myline);
  6. myline := StringofChar('b',120);
  7. writeln(myline);
  8. end.

The result  under Lubuntu 16.04  Lazarus 1.8.2 is in attachment. The lines with 120 characters are correctly displayed.
The project is in attachment. Processutils.pas coming from fpcUpDeluxe project has a MIT or LGPL licence.

Friendly, J.P

Hello,

Processutils.pas coming from fpcUpDeluxe does not contain TProcessEx class? Did I miss something or it is renamed in meantime?
Where can it be downloaded?

Roland57

  • Sr. Member
  • ****
  • Posts: 421
    • msegui.net
Re: Output from TProcess breaks lines over 80 characters
« Reply #28 on: March 15, 2021, 09:25:36 pm »
Processutils.pas coming from fpcUpDeluxe does not contain TProcessEx class? Did I miss something or it is renamed in meantime?
Where can it be downloaded?

Indeed, it seems that the unit has been remade. The old version of the unit is included in the project attached above.

Regards.

Roland
« Last Edit: March 15, 2021, 09:29:11 pm by Roland57 »
My projects are on Gitlab and on Codeberg.

 

TinyPortal © 2005-2018