Input and output pipe in Lazarus TProcess

Viewed 205

I would like to make a terminal with a Lazarus GUI application. But I'm in trouble. And I hope someone can help me, please.

Question1: The Chinese and other special chars cannot display normally, I would like to know how to fix this problem. (code)Class of the thread and "run" button on click event

screenshot

Question2: I want to know how to input some command into the console. I tried to start a Windows cmd, and use "winver" command. But when I click the button, nothing happened.

The send command button

1 Answers

Winver is not console but a GUI program. To run a program with output into memo, use the following code, which retrieves version using the cmd.exe "ver" command. You can try to use this template for the first question too.

unit mainprocesstomemo;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Process, Pipes;

Type
  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
  public
    procedure ProcessEvent(Sender,Context : TObject;Status:TRunCommandEventCode;const Message:string);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TProcessMemo }
Type

 TProcessToMemo = class(TProcess)
                            public
                            fmemo : Tmemo;
                            bytesprocessed : integer;
                            fstringsadded : integer;
                            function ReadInputStream(p:TInputPipeStream;var BytesRead:integer;var DataLength:integer;var Data:string;MaxLoops:integer=10):boolean;override;
                          end;



function RunCommandMemo(const exename:TProcessString;const commands:array of TProcessString;out outputstring:string; Options : TProcessOptions = [];SWOptions:TShowWindowOptions=swoNone;memo:TMemo=nil;runrefresh : TOnRunCommandEvent=nil ):boolean;
Var
    p : TProcessToMemo;
    i,
    exitstatus : integer;
    ErrorString : String;
begin
  p:=TProcessToMemo.create(nil);
  if Options<>[] then
    P.Options:=Options - [poRunSuspended,poWaitOnExit];
  p.options:=p.options+[poRunIdle];

  P.ShowWindow:=SwOptions;
  p.Executable:=exename;
  if high(commands)>=0 then
   for i:=low(commands) to high(commands) do
     p.Parameters.add(commands[i]);
  p.fmemo:=memo;
  p.OnRunCommandEvent:=runrefresh;
  try
    result:=p.RunCommandLoop(outputstring,errorstring,exitstatus)=0;
  finally
    p.free;
  end;
  if exitstatus<>0 then result:=false;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var s : string;
begin
//RunCommandMemo('testit',[],s,[],swonone,memo1,ProcessEvent);
  RunCommandMemo('cmd.exe',['/w','/c','ver'],s,[],swonone,memo1,ProcessEvent);
end;

procedure TForm1.ProcessEvent(Sender, Context: TObject;
  Status: TRunCommandEventCode; const Message: string);
begin
  if status in [RunCommandIdle, RunCommandFinished] then
    begin
      if status =RunCommandFinished then
        begin
          memo1.lines.add(' process finished');
        end;
      if tprocesstomemo(sender).fstringsadded>0 then
       begin
         tprocesstomemo(sender).fstringsadded:=0;
//         memo1.lines.add('Handle:'+inttostr(tprocesstomemo(sender).ProcessHandle));
         memo1.refresh;
       end;
      sleep(10);
      application.ProcessMessages;
    end;
end;

{ TProcessToMemo }


function TProcessToMemo.ReadInputStream(p:TInputPipeStream;var BytesRead:integer;var DataLength:integer;var Data:string;MaxLoops:integer=10):boolean;
var lfpos : integer;
    crcorrectedpos:integer;
    stradded : integer;
    newstr : string;
begin
  Result:=inherited ReadInputStream(p, BytesRead, DataLength, data, MaxLoops);
  if (result) and (bytesread>bytesprocessed)then
    begin
      stradded:=0;
      lfpos:=pos(#10,data,bytesprocessed+1);
      while (lfpos<>0) and (lfpos<=bytesread) do
        begin
          crcorrectedpos:=lfpos;
          if (crcorrectedpos>0) and (data[crcorrectedpos-1]=#13) then
             dec(crcorrectedpos);
          newstr:=copy(data,bytesprocessed+1,crcorrectedpos-bytesprocessed-1);
          fmemo.lines.add(newstr);
           inc(stradded);
          bytesprocessed:=lfpos;
          lfpos:=pos(#10,data,bytesprocessed+1);
        end;
      inc(fstringsadded,stradded); // check idle event.
    end;
end;

end.

I don't know minecraft server, and many external programs might do weird things to the console. But a simple combination of programs to test with is here http://www.stack.nl/~marcov/files/processmemodemo.zip

Related