Italian community of Lazarus and Free Pascal

Programmazione => LCL => Topic aperto da: Fabio - Novembre 29, 2011, 04:10:27 pm

Titolo: TProcess e lettura da commandline
Inserito da: Fabio - Novembre 29, 2011, 04:10:27 pm
Avrei necessità di eseguire un comando da console e leggerne l'output generato.

Ho trovato questo esempio
Codice: [Seleziona]
procedure TfrmMain.btnScanClick(Sender: TObject);
begin
     if lstInputs.Items.Count = 0 then exit;
     Application.ProcessMessages;
     Hbk.CommandLine := 'HandbrakeCLI -i ' + '"' + lstInputs.Items[0] + '"' + ' -t 0';
     //Hbk.CommandLine := 'HandbrakeCLI -h';
     //Hbk.Options := [poUsePipes];
     Hbk.Options := [poUsePipes, poStderrToOutPut];
     //Hbk.ShowWindow := swoShow;
     Hbk.Execute;
     //HbkStr.LoadFromStream(Hbk.Output);
     //HbkStr.SaveToFile('HbkLog.txt');
     while Hbk.running do
     begin
          M.SetSize(BytesRead + READ_BYTES);
          n := Hbk.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
          if n > 0 then
          begin
               Inc(BytesRead,n);
               //Write('.');
          end
          else
          begin
               sleep(200);
          end;
     end;

     repeat
           M.SetSize(BytesRead + READ_BYTES);
           n := Hbk.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
           if n > 0 then
           begin
               Inc(BytesRead,n);
               //Write('.');
           end;
     until n <= 0;

     //if BytesRead > 0 then Writeln;
     M.SetSize(BytesRead);
     //HbkStr.LoadFromStream(M);
     //HbkStr.SaveToFile('HbkLog.txt');
     mmoOutputs.Lines.Clear;
     mmoOutputs.Lines.BeginUpdate;
     mmoOutputs.Lines.LoadFromStream(M);
     mmoOutputs.Lines.EndUpdate;

end;                   
http://www.lazarus.freepascal.org/index.php?topic=10898.0

Ma mi mancano alcune parti esempio quel "M" cos'è ?

Ciao.
Titolo: Re:TProcess e lettura da commandline
Inserito da: Microges2000 - Novembre 29, 2011, 04:23:11 pm
Usa TProcess come spiegato qui: http://wiki.freepascal.org/Executing_External_Programs#TProcess

TProcess è indipendente dalla piattaforma e dal programma (console o meno)

nota che nel primo esempio non viene ripreso l'output che si puo' prelevare con AProcess.Output (come spiegato nel secondo esempio)
Titolo: Re:TProcess e lettura da commandline
Inserito da: Fabio - Novembre 29, 2011, 04:25:10 pm
Provo e faccio sapere.

Grazie.
Titolo: Re:TProcess e lettura da commandline
Inserito da: Fabio - Novembre 29, 2011, 04:45:41 pm
Perfetto, l'esempio veloce fatto per prova, un campo testo con il nome del processo ( es TASKLIST.EXE ) un pulsante per eseguire la procedura e un campo memo per l'output catturato ( ovviamente è tutto da ottimizzare ma è una base di partenza funzionale) :

Codice: [Seleziona]
unit Unit1; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, process, FileUtil, Forms, Controls, Graphics, Dialogs,
  StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    Process1: TProcess;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
const
  READ_BYTES = 2048;

var
  OutputLines: TStringList;
  MemStream: TMemoryStream;
  NumBytes: LongInt;
  BytesRead: LongInt;

begin

  MemStream := TMemoryStream.Create;
  BytesRead := 0;

  Process1.CommandLine := Edit1.Text;
  Process1.Options := [poUsePipes];
  Process1.Execute;
  while Process1.Running do
  begin
    // make sure we have room
    MemStream.SetSize(BytesRead + READ_BYTES);
    NumBytes := Process1.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
    if NumBytes > 0 then
    begin
      Inc(BytesRead, NumBytes);
    end
    else
    begin
      Sleep(100); // no data, wait 100 ms
    end;
  end;

  repeat
    // make sure we have room
    MemStream.SetSize(BytesRead + READ_BYTES);

    // try reading it
    NumBytes := Process1.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
    if NumBytes > 0
    then begin
      Inc(BytesRead, NumBytes);
    end;
  until NumBytes <= 0;

  MemStream.SetSize(BytesRead);

  OutputLines := TStringList.Create;
  OutputLines.LoadFromStream(MemStream);
  for NumBytes := 0 to OutputLines.Count - 1 do
  begin
    Memo1.Lines.Add(OutputLines[NumBytes]);
  end;
  OutputLines.Free;
  MemStream.Free;

end;

end.

Grazie.