Recent

Author Topic: Piping Console Output into GUI Application  (Read 7842 times)

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 9336
  • FPC developer.
Re: Piping Console Output into GUI Application
« Reply #15 on: June 09, 2021, 10:54:20 pm »
My solution will only trap Pascal output.

If he means gtk errors etc, I don't know.

Maybe to make it more clear, if I start the application in a console "./libsockuse" or "sudo ./libsockuse" (this is at least required if I want to use it with root rights to set CAN configuration), it will show the (error) messages in that shell window. This is what I want to catch and show it in the application itself.

Those might not even be application errors, but kernel (module) errors redirected to the console.

Maybe directly interacting with sysconsole pty or so?

Anyway I suggest to rethink that. It sounds simple, but it probably isn't. (and by that I mean that it might be hard to do that from _any_ process, not just a FPC compiled one)

Fred vS

  • Hero Member
  • *****
  • Posts: 2221
    • StrumPract is the musicians best friend
Re: Piping Console Output into GUI Application
« Reply #16 on: June 09, 2021, 11:18:23 pm »
Hello.

Thanks to Warfley (sorry I did not re-find the post), this will redirect all message-console, including gtk errors etc, into a text file.

Code: Pascal  [Select][+][-]
  1. program errorlog;
  2.   uses
  3.    ... ,  Classes, BaseUnix;
  4.    var
  5.      fs: TFileStream;
  6.    begin
  7.      fs := TFileStream.Create('error.log', fmOpenReadWrite or fmCreate);
  8.      FpDup2(fs.Handle, StdErrorHandle);
  9.        ...  // all your program stuff
  10.      Application.run; // Inside application, catch fs data
  11.      fs.free;
  12.     end.

Maybe you could catch the 'error.log' data in the program himself (close fs, then read error.log).
« Last Edit: June 10, 2021, 04:23:48 pm by Fred vS »
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

engkin

  • Hero Member
  • *****
  • Posts: 2818
Re: Piping Console Output into GUI Application
« Reply #17 on: June 10, 2021, 02:34:38 am »
Yes, I agree with Fred. I found a SO post that solved this problem using Dup2 and pipes. This way you don't need a "file". I tested the idea on an Android terminal. Seemed to work:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   Classes, SysUtils, BaseUnix
  7.   {$IFDEF UNIX}
  8.   {$IFDEF UseCThreads}
  9.   ,cthreads
  10.   {$ENDIF}
  11.   {$ENDIF}
  12.   { you can add units after this };
  13. {
  14. https://stackoverflow.com/questions/955962/how-to-buffer-stdout-in-memory-and-write-it-from-a-dedicated-thread
  15. }
  16. function Test(AHandle:cInt; var APipe: tfildes):cint;
  17. var
  18.   saved: cint;
  19. begin
  20.   Result:=-1;
  21.   saved:=FpDup(AHandle);
  22.   if FpPipe(APipe)<>0 then
  23.   begin
  24.     WriteLn('FpPipe failed.');
  25.     exit;
  26.   end;
  27.   FpDup2(APipe[1], AHandle);
  28.   FpClose(APipe[1]);
  29.   Result:=saved;
  30. end;
  31.  
  32.  
  33. const
  34.   MAX_LEN=40;
  35. type
  36.   TBuffer=array[0..MAX_LEN-1] of char;
  37. var
  38.   Pipe: tfildes=(0,0);
  39.   saved_, TestHandle: cint;
  40.   buffer:TBuffer;
  41. begin
  42.   buffer:=Default(TBuffer);
  43.  
  44.   TestHandle:=StdOutputHandle;
  45.   //TestHandle:=Test(StdErrorHandle);
  46.  
  47.   WriteLn('Test Before');
  48.   saved_:=Test(TestHandle, Pipe);
  49.   WriteLn('Test After'); //<---- this will be sent to the pipe
  50.   Flush(StdOut);
  51.  
  52.   fpread(Pipe[0], buffer[0], MAX_LEN); // read from pipe into buffer
  53.  
  54.   FpDup2(saved_, StdOutputHandle);  // reconnect stdout for testing
  55.  
  56.   WriteLn(Format('read: %s', [buffer]));
  57.   readLn;
  58. end.

To test on Android:
Code: Text  [Select][+][-]
  1. adb push project1 "/data/local/tmp"
  2. adb shell chmod 755 /data/local/tmp/project1
  3. adb shell /data/local/tmp/project1

The output:
Quote
Test Before
read: Test After

On Linux, StdErrorHandle is hard coded:
Code: Pascal  [Select][+][-]
  1. const
  2.   UnusedHandle    = -1;
  3.   StdInputHandle  = 0;
  4.   StdOutputHandle = 1;
  5.   StdErrorHandle  = 2;

I believe it should work with kernel errors as well.

MarkMLl

  • Hero Member
  • *****
  • Posts: 2708
Re: Piping Console Output into GUI Application
« Reply #18 on: June 10, 2021, 08:52:59 am »
As a slight aside: Marco, am I correct in that the Lazarus IDE doesn't have an interactive shell-out facility?

Afaik indeed it doesn't. It was designed for systems that could run more tasks in parallel, so there was no need for functionality to suspend the IDE to run a shell like old DOS IDEs did.

Thanks for that, just checking I've not overlooked anything. I've got a vague recollection of a couple of cases where it would have been useful although I can't remember the exact details... and of course there's the "shell-like" facilities of "change current directory" and "set shell/environment variable".

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Edson

  • Hero Member
  • *****
  • Posts: 1175
Re: Piping Console Output into GUI Application
« Reply #19 on: June 10, 2021, 08:10:41 pm »
Maybe I don't understand well the problem but in case you need to capture the output or error of a process , you can try my library: https://github.com/t-edson/UnTerminal

If you need to emulate a terminal, to control special inputs like "sudo" needs, I wrote an article about that: http://blogdetito.com/2016/12/04/el-inicio-de-un-terminal-con-linux-y-free-pascal/
Lazarus 2.0.10 - FPC 3.2.0 - x86_64-win64 on Windows 8

 

TinyPortal © 2005-2018