【问题标题】:Input and output pipe in Lazarus TProcessLazarus TProcess 中的输入和输出管道
【发布时间】:2022-10-18 21:37:04
【问题描述】:

我想用 Lazarus GUI 应用程序制作一个终端。但我有麻烦了。我希望有人可以帮助我,拜托。

问题1: 中文和其他特殊字符无法正常显示,我想知道如何解决这个问题。 (code)Class of the thread and "run" button on click event

screenshot

问题2: 我想知道如何在控制台中输入一些命令。我尝试启动 Windows cmd,并使用“winver”命令。但是当我点击按钮时,什么也没发生。

The send command button

【问题讨论】:

    标签: process lazarus


    【解决方案1】:

    Winver 不是控制台,而是一个 GUI 程序。要运行程序并在备忘录中输出,请使用以下代码,该代码使用 cmd.exe“ver”命令检索版本。您也可以尝试将此模板用于第一个问题。

        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.
    

    我不知道我的世界服务器,许多外部程序可能会对控制台做一些奇怪的事情。但是这里有一个简单的程序组合来测试http://www.stack.nl/~marcov/files/processmemodemo.zip

    【讨论】:

    • 谢谢。启动程序后如何输入命令?为了例子,我想启动一个 Minecraft 服务器,并在控制台中使用 TProcess 执行命令。
    • 见最后一段
    猜你喜欢
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多