Difference between revisions of "Executing External Programs/pt"

From Lazarus wiki
Jump to navigationJump to search
 
m (Fixed syntax highlighting)
 
(9 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{Executing External Programs}}
 
{{Executing External Programs}}
  
== Introduction ==
+
== Introdução ==
  
There are multiple ways to run an external program, but I will only focus on one. TProcess.
+
Existem várias formas de executar um programa externo, mas eu destacarei apenas uma. TProcess.
 +
 
 +
Se você sempre usou '''ShellExecute''' e/ou '''WinExec''' em Delphi, então você pode começar a usar TProcess como uma alternativa em FPC/Lazarus (isso é válido também se você está executando Lazarus em um Linux, porque TProcess é multi-plataforma).
 +
 
 +
'''Nota:''' FPC/Lazarus tem suporte à '''ShellExecute''' e/ou '''WinExec''', mas este suporte é somente em Win32. Se o seu programa é multi-plataforma, então use TProcess, é o melhor caminho!
 +
 
 +
== SysUtils.ExecuteProcess ==
 +
 
 +
O caminho mais simples se você não necessita de "pipes" ou qualquer outro controle é simplesmente usar SysUtils.ExecuteProcess('/full/path/to/binary',['arg1','arg2']);
  
 
==TProcess==
 
==TProcess==
You can use TProcess to launch external programs. Some of the benefits of using TProcess are that it is:
+
Você pode usar TProcess para iniciar programas externos. Alguns dos beneficios de usar TProcess:
  
*Platform Independent
+
*Plataforma Independente
*Capable of reading from stdout and writing to stdin.
+
*Capacidade de leitura da saída e escrita da entrada.
  
===A Simple Example===
+
Nota: TProcess não é um terminal/shell! Você não pode executar diretamente scripts ou redirecionar a saida usando operadores como "|", ">", "<", "&" etc. É possível obter o mesmo resultado com TProcess usando pascal, alguns exemplos estão a seguir..
  // This is a demo program that shows how to launch
+
 
  // an external program.
+
===Um Exemplo Simples===
 +
<syntaxhighlight lang=pascal>
 +
  // Este é um programa de demonstração que mostra como executar
 +
  // um programa externo.
 +
 
  program launchprogram;
 
  program launchprogram;
+
  // Aqui são incluidos arquivos que terão funções úteis
  // Here we include files that have useful functions
+
  // e procedures que nós precisamos.
  // and procedures we will need.
+
  uses
  uses  
 
 
   Classes, SysUtils, Process;
 
   Classes, SysUtils, Process;
 
   
 
   
  // This is defining the var "AProcess" as a variable
+
  // Este ponto é definida a variável "AProcess" como uma variável
  // of the type "TProcess"
+
  // do tipo "TProcess"
  var  
+
  var
 
   AProcess: TProcess;
 
   AProcess: TProcess;
 
   
 
   
  // This is where our program starts to run
+
  // Aqui é onde o nosso programa inicia a execução
 
  begin
 
  begin
   // Now we will create the TProcess object, and
+
   // Agora nós criaremos o objeto TProcess, e
   // assign it to the var AProcess.
+
   // associamos ele à variável AProcess.
 
   AProcess := TProcess.Create(nil);
 
   AProcess := TProcess.Create(nil);
 
   
 
   
   // Tell the new AProcess what the command to execute is.
+
   // Mostraremos ao novo AProcess qual é o comando para ele executar.
   // Let's use the FreePascal compiler
+
   // Vamos usar o Compilador FreePascal
 
   AProcess.CommandLine := 'ppc386 -h';
 
   AProcess.CommandLine := 'ppc386 -h';
 
   
 
   
   // We will define an option for when the program
+
   // Nós definiremos uma opção para onde o programa
   // is run. This option will make sure that our program
+
   // é executado. Esta opção verificará que nosso programa
   // does not continue until the program we will launch
+
   // não continue enquanto o programa que nós executamos
   // has stopped running.               vvvvvvvvvvvvvv
+
   // não pare de executar.               vvvvvvvvvvvvvv
 
   AProcess.Options := AProcess.Options + [poWaitOnExit];
 
   AProcess.Options := AProcess.Options + [poWaitOnExit];
 
   
 
   
   // Now that AProcess knows what the commandline is
+
   // Agora que AProcess sabe qual é a linha de comando
   // we will run it.
+
   // nós executaremos ele.
 
   AProcess.Execute;
 
   AProcess.Execute;
 
   
 
   
   // This is not reached until ppc386 stops running.
+
   // Esta parte não é alcançada enquanto ppc386 não parar a execução.
   AProcess.Free;  
+
   AProcess.Free;
 
  end.
 
  end.
 +
</syntaxhighlight>
  
That's it! You have just learned how to run an external program from inside your own program.
+
É isso! Você aprendeu razoavelmente como executar um programa externo de dentro do seu próprio programa.
 
 
 
 
  
===An Improved Example===
+
===Um Exemplo aperfeiçoado===
That's nice, but how do I read the Output of a program that I have run?
+
Isso é bom, mas como eu leio a saida de um programa que eu executei?
  
Well, let's expand our example a little and do just that:
+
Bom, vamos expandir nosso exemplo um pouco e faremos apenas isso:
  
  // This is a demo program that shows how to launch
+
<syntaxhighlight lang=pascal>
  // an external program and read from it's output.
+
  // Este é um programa que mostra como executar
 +
  // um programa externo e ler sua saída.
 
  program launchprogram;
 
  program launchprogram;
 
   
 
   
  // Here we include files that have useful functions
+
  // Aqui são incluidos arquivos que terão funções úteis
  // and procedures we will need.
+
  // e procedures que nós precisamos.
  uses  
+
  uses
 
   Classes, SysUtils, Process;
 
   Classes, SysUtils, Process;
 
   
 
   
  // This is defining the var "AProcess" as a variable
+
  // Neste ponto é definida a variável "AProcess" como uma variável
  // of the type "TProcess"
+
  // do tipo "TProcess"
  // Also now we are adding a TStringList to store the
+
  // Também agora nós adicionamos uma TStringList para armazenar os
  // data read from the programs output.
+
  // dados lidos da saida do programa.
  var  
+
  var
 
   AProcess: TProcess;
 
   AProcess: TProcess;
 
   AStringList: TStringList;
 
   AStringList: TStringList;
 
   
 
   
  // This is where our program starts to run
+
  // Aqui é onde o nosso programa inicia a execução
 
  begin
 
  begin
   // Now we will create the TProcess object, and
+
   // Agora nós criaremos o objeto TProcess, e
   // assign it to the var AProcess.
+
   // associamos ele à variável AProcess.
 
   AProcess := TProcess.Create(nil);
 
   AProcess := TProcess.Create(nil);
 
   
 
   
   // Create the TStringList object.
+
   // Cria o objeto TStringList.
 
   AStringList := TStringList.Create;
 
   AStringList := TStringList.Create;
 
   
 
   
   // Tell the new AProcess what the command to execute is.
+
   // Mostraremos ao novo AProcess qual é o comando para ele executar.
   // Let's use the FreePascal compiler
+
   // Vamos usar o Compilador FreePascal
 
   AProcess.CommandLine := 'ppc386 -h';
 
   AProcess.CommandLine := 'ppc386 -h';
 
   
 
   
   // We will define an option for when the program
+
   // Nós definiremos uma opção para onde o programa
   // is run. This option will make sure that our program
+
   // é executado. Esta opção verificará que nosso programa
   // does not continue until the program we will launch
+
   // não continue enquanto o programa que nós executamos
   // has stopped running. Also now we will tell it that
+
   // não pare de executar. Também agora vamos mostrar a ele que
   // we want to read the output of the file.
+
   // que nós precisamos ler a saída do arquivo.
 
   AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
 
   AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
 
   
 
   
   // Now that AProcess knows what the commandline is
+
   // Agora que AProcess sabe qual é a linha de comando
   // we will run it.
+
   // nós executaremos ele.
 
   AProcess.Execute;
 
   AProcess.Execute;
 
 
  // This is not reached until ppc386 stops running.
 
 
   
 
   
   // Now read the output of the program we just ran
+
   // Esta parte não é alcançada enquanto ppc386 não parar a execução.
   // into the TStringList.
+
 +
  // Agora lida a saida do programa nós colocaremos
 +
   // ela na TStringList.
 
   AStringList.LoadFromStream(AProcess.Output);
 
   AStringList.LoadFromStream(AProcess.Output);
 
+
   // Save the output to a file.
+
   // Salvamos a saida para um arquivo.
 
   AStringList.SaveToFile('output.txt');
 
   AStringList.SaveToFile('output.txt');
 
   
 
   
   // Now that the file is saved we can free the
+
   // Agora que o arquivo foi salvo nós podemos liberar a
   // TStringList and the TProcess.
+
   // TStringList e o TProcess.
 
   AStringList.Free;
 
   AStringList.Free;
   AProcess.Free;  
+
   AProcess.Free;
 
  end.
 
  end.
 +
</syntaxhighlight>
  
===Reading large output===
+
===Lendo a grande saida===
In the previous example we waited until the program exited. Then we read, what the program has written to its output. But suppose the program writes a lot of data to the output, the pipe becomes full and needs to read. But the calling program doesn't read from it, until the called program has ended. A dead lock occurs.
+
No exemplo anterior nós esperamos enquanto o programa finalizava. Então nós lemos o que o programa escreveu em sua saida. Mas suponhamos que o programa escreva uma série de dados para a saída, os "pipes" virão carregados e precisam ser lidos. Mas chamando o programa não lerá dele, enquanto o programa chamado não finalizar. Um fechamento inoperante acontecerá.
  
The following example therefore doesn't use poWaitOnExit, but reads from the output, while the program is still running. The output is stored in a memory stream, that can be used later to read the output into a TStringList.
+
O exemplo seguinte então não usa o poWaitOnExit, mas lê a saida, enquanto o programa tranquilamente é executado. A saida é armazenada no fluxo de memória, que pode depois ser usado para ler a saida em uma TStringList.
  
program procoutlarge;
+
<syntaxhighlight lang=pascal> program procoutlarge;
 
  {
 
  {
 
     Copyright (c) 2004 by Marc Weustink
 
     Copyright (c) 2004 by Marc Weustink
Line 134: Line 146:
 
  const
 
  const
 
   READ_BYTES = 2048;
 
   READ_BYTES = 2048;
 
+
 
  var
 
  var
 
   S: TStringList;
 
   S: TStringList;
Line 143: Line 155:
 
   
 
   
 
  begin
 
  begin
   // We cannot use poWaitOnExit here since we don't
+
   // Nós não podemos usar poWaitOnExit aqui visto que nós não
   // know the size of the output. On Linux the size of the
+
   // conhecemos o tamanho da saída. No Linux o tamanho do
   // output pipe is 2 kB. If the output data is more, we
+
   // pipe de saida é 2 kB. Se os dados da saída são maiores, nós
   // need to read the data. This isn't possible since we are
+
   // precisamos ler os dados. Isto não é possível visto que nós estamos
   // waiting. So we get a deadlock here.
+
   // esperando. Deste modo nós recebemos um deadlock aqui.
 
   //
 
   //
   // A temp Memorystream is used to buffer the output
+
   // Uma Memorystream temporária é usada para armazenar a saida
 
+
 
   M := TMemoryStream.Create;
 
   M := TMemoryStream.Create;
 
   BytesRead := 0;
 
   BytesRead := 0;
Line 157: Line 169:
 
   P.CommandLine := 'ppc386 -va bogus.pp';
 
   P.CommandLine := 'ppc386 -va bogus.pp';
 
   P.Options := [poUsePipes];
 
   P.Options := [poUsePipes];
   WriteLn('-- executing --');
+
   WriteLn('-- executando --');
 
   P.Execute;
 
   P.Execute;
 
   while P.Running do
 
   while P.Running do
   begin        
+
   begin
     // make sure we have room
+
     // Verifica se temos dependências
 
     M.SetSize(BytesRead + READ_BYTES);
 
     M.SetSize(BytesRead + READ_BYTES);
   
+
     // try reading it
+
     // tenta ler ela
 
     n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
 
     n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
     if n > 0  
+
     if n > 0
 
     then begin
 
     then begin
 
       Inc(BytesRead, n);
 
       Inc(BytesRead, n);
 
       Write('.')
 
       Write('.')
 
     end
 
     end
     else begin    
+
     else begin
       // no data, wait 100 ms
+
       // sem dados, espera 100 ms
       Sleep(100);  
+
       Sleep(100);
 
     end;
 
     end;
 
   end;
 
   end;
   // read last part
+
   // lê a última parte
 
   repeat
 
   repeat
     // make sure we have room
+
     // verifica se temos dependências
 
     M.SetSize(BytesRead + READ_BYTES);
 
     M.SetSize(BytesRead + READ_BYTES);
 
     // try reading it
 
     // try reading it
 
     n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
 
     n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
     if n > 0  
+
     if n > 0
 
     then begin
 
     then begin
 
       Inc(BytesRead, n);
 
       Inc(BytesRead, n);
Line 189: Line 201:
 
   until n <= 0;
 
   until n <= 0;
 
   if BytesRead > 0 then WriteLn;
 
   if BytesRead > 0 then WriteLn;
   M.SetSize(BytesRead);  
+
   M.SetSize(BytesRead);
   WriteLn('-- executed --');
+
   WriteLn('-- executado --');
 
+
 
   S := TStringList.Create;
 
   S := TStringList.Create;
 
   S.LoadFromStream(M);
 
   S.LoadFromStream(M);
   WriteLn('-- linecount = ', S.Count, ' --');
+
   WriteLn('-- número de linhas = ', S.Count, ' --');
 
   for n := 0 to S.Count - 1 do
 
   for n := 0 to S.Count - 1 do
 
   begin
 
   begin
 
     WriteLn('| ', S[n]);
 
     WriteLn('| ', S[n]);
 
   end;
 
   end;
   WriteLn('-- end --');
+
   WriteLn('-- final --');
 
   S.Free;
 
   S.Free;
 
   P.Free;
 
   P.Free;
 
   M.Free;
 
   M.Free;
  end.
+
  end.</syntaxhighlight>
 +
 
 +
=== Usando a entrada e saida de um TProcess ===
 +
Veja o exemplo processemo no [https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/examples/process Lazarus-CCR SVN].
 +
 
 +
=== Dicas no uso de TProcess ===
 +
Se você está criando um programa multi-plataforma, você pode mudar a linha de comando de acordo com o SO (Sistema Operacional), usando diretivas "{$IFDEF}s" and "{$ENDIF}s".
 +
 
 +
Exemplo:
 +
<syntaxhighlight lang=pascal> {...}
 +
  AProcess:TProcess.Create(nil)
 +
  {$IFDEF WIN32}
 +
  AProcess.CommandLine := 'calc.exe'; //Calculadora do Windows
 +
  {$ENDIF}
 +
  {$IFDEF LINUX}
 +
  AProcess.CommandLine := 'kcalc'; //Calculadora do KDE
 +
  {$ENDIF}
 +
  AProcess.Execute; //em alternativa, você pode usar AProcess.Active:=True
 +
{...}</syntaxhighlight>
 +
 
  
=== Example of "talking" with aspell process ===
+
=== Exemplo de "conversa" com um processo aspell ===
  
Inside [http://pasdoc.sourceforge.net/ pasdoc] source code you can find two units that perform spell-checking by "talking" with running aspell process through pipes:
+
Dentro do código-fonte do [http://pasdoc.sourceforge.net/ pasdoc] você pode encontrar duas units que executam 'spell-checking' por uma conversa com o processo aspell em execução através de "pipes":
  
* [http://cvs.sourceforge.net/viewcvs.py/*checkout*/pasdoc/pasdoc/source/component/PasDoc_ProcessLineTalk.pas PasDoc_ProcessLineTalk.pas unit] implements TProcessLineTalk class, descendant of TProcess, that can be easily used to talk with any process on a line-by-line basis.
+
* [http://cvs.sourceforge.net/viewcvs.py/*checkout*/pasdoc/pasdoc/source/component/PasDoc_ProcessLineTalk.pas A unit PasDoc_ProcessLineTalk.pas] implementa a classe TProcessLineTalk, descendente de TProcess, que pode ser facilmente usada para conversar com qualquer processo em uma base de linha-por-linha.
  
* [http://cvs.sourceforge.net/viewcvs.py/*checkout*/pasdoc/pasdoc/source/component/PasDoc_Aspell.pas PasDoc_Aspell.pas units] implements TAspellProcess class, that performs spell-checking by using underlying TProcessLineTalk instance to execute aspell and communicate with running aspell process.
+
* [http://cvs.sourceforge.net/viewcvs.py/*checkout*/pasdoc/pasdoc/source/component/PasDoc_Aspell.pas A unit PasDoc_Aspell.pas] implementa a classe TAspellProcess, que executa 'spell-checking' pela utilização de uma instância subjacente TProcessListTalk para executar aspell e comunicar com o processo aspell em execução.
  
Both units are rather independent from the rest of pasdoc sources, so they may serve as real-world examples of using TProcess to run and communicate through pipes with other program.
+
Ambas as units são um pouco independentes do resto dos fontes pasdoc, assim elas pode servir como exemplos reais da utilização de TProcess para executar comunicação através de pipes com outros programas.

Latest revision as of 12:58, 14 February 2020

Deutsch (de) English (en) español (es) français (fr) italiano (it) 日本語 (ja) Nederlands (nl) polski (pl) português (pt) русский (ru) slovenčina (sk) 中文(中国大陆)‎ (zh_CN)

Introdução

Existem várias formas de executar um programa externo, mas eu destacarei apenas uma. TProcess.

Se você sempre usou ShellExecute e/ou WinExec em Delphi, então você pode começar a usar TProcess como uma alternativa em FPC/Lazarus (isso é válido também se você está executando Lazarus em um Linux, porque TProcess é multi-plataforma).

Nota: FPC/Lazarus tem suporte à ShellExecute e/ou WinExec, mas este suporte é somente em Win32. Se o seu programa é multi-plataforma, então use TProcess, é o melhor caminho!

SysUtils.ExecuteProcess

O caminho mais simples se você não necessita de "pipes" ou qualquer outro controle é simplesmente usar SysUtils.ExecuteProcess('/full/path/to/binary',['arg1','arg2']);

TProcess

Você pode usar TProcess para iniciar programas externos. Alguns dos beneficios de usar TProcess:

  • Plataforma Independente
  • Capacidade de leitura da saída e escrita da entrada.

Nota: TProcess não é um terminal/shell! Você não pode executar diretamente scripts ou redirecionar a saida usando operadores como "|", ">", "<", "&" etc. É possível obter o mesmo resultado com TProcess usando pascal, alguns exemplos estão a seguir..

Um Exemplo Simples

 // Este é um programa de demonstração que mostra como executar
 // um programa externo.
 
 program launchprogram;
 // Aqui são incluidos arquivos que terão funções úteis
 // e procedures que nós precisamos.
 uses
   Classes, SysUtils, Process;
 
 // Este ponto é definida a variável "AProcess" como uma variável
 // do tipo "TProcess"
 var
   AProcess: TProcess;
 
 // Aqui é onde o nosso programa inicia a execução
 begin
   // Agora nós criaremos o objeto TProcess, e
   // associamos ele à variável AProcess.
   AProcess := TProcess.Create(nil);
 
   // Mostraremos ao novo AProcess qual é o comando para ele executar.
   // Vamos usar o Compilador FreePascal
   AProcess.CommandLine := 'ppc386 -h';
 
   // Nós definiremos uma opção para onde o programa
   // é executado. Esta opção verificará que nosso programa
   // não continue enquanto o programa que nós executamos
   // não pare de executar.               vvvvvvvvvvvvvv
   AProcess.Options := AProcess.Options + [poWaitOnExit];
 
   // Agora que AProcess sabe qual é a linha de comando
   // nós executaremos ele.
   AProcess.Execute;
 
   // Esta parte não é alcançada enquanto ppc386 não parar a execução.
   AProcess.Free;
 end.

É isso! Você aprendeu razoavelmente como executar um programa externo de dentro do seu próprio programa.

Um Exemplo aperfeiçoado

Isso é bom, mas como eu leio a saida de um programa que eu executei?

Bom, vamos expandir nosso exemplo um pouco e faremos apenas isso:

 // Este é um programa que mostra como executar
 // um programa externo e ler sua saída.
 program launchprogram;
 
 // Aqui são incluidos arquivos que terão funções úteis
 // e procedures que nós precisamos.
 uses
   Classes, SysUtils, Process;
 
 // Neste ponto é definida a variável "AProcess" como uma variável
 // do tipo "TProcess"
 // Também agora nós adicionamos uma TStringList para armazenar os
 // dados lidos da saida do programa.
 var
   AProcess: TProcess;
   AStringList: TStringList;
 
 // Aqui é onde o nosso programa inicia a execução
 begin
   // Agora nós criaremos o objeto TProcess, e
   // associamos ele à variável AProcess.
   AProcess := TProcess.Create(nil);
 
   // Cria o objeto TStringList.
   AStringList := TStringList.Create;
 
   // Mostraremos ao novo AProcess qual é o comando para ele executar.
   // Vamos usar o Compilador FreePascal
   AProcess.CommandLine := 'ppc386 -h';
 
   // Nós definiremos uma opção para onde o programa
   // é executado. Esta opção verificará que nosso programa
   // não continue enquanto o programa que nós executamos
   // não pare de executar. Também agora vamos mostrar a ele que
   // que nós precisamos ler a saída do arquivo.
   AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
 
   // Agora que AProcess sabe qual é a linha de comando
   // nós executaremos ele.
   AProcess.Execute;
 
   // Esta parte não é alcançada enquanto ppc386 não parar a execução.
 
   // Agora lida a saida do programa nós colocaremos
   // ela na TStringList.
   AStringList.LoadFromStream(AProcess.Output);
 
   // Salvamos a saida para um arquivo.
   AStringList.SaveToFile('output.txt');
 
   // Agora que o arquivo foi salvo nós podemos liberar a
   // TStringList e o TProcess.
   AStringList.Free;
   AProcess.Free;
 end.

Lendo a grande saida

No exemplo anterior nós esperamos enquanto o programa finalizava. Então nós lemos o que o programa escreveu em sua saida. Mas suponhamos que o programa escreva uma série de dados para a saída, os "pipes" virão carregados e precisam ser lidos. Mas chamando o programa não lerá dele, enquanto o programa chamado não finalizar. Um fechamento inoperante acontecerá.

O exemplo seguinte então não usa o poWaitOnExit, mas lê a saida, enquanto o programa tranquilamente é executado. A saida é armazenada no fluxo de memória, que pode depois ser usado para ler a saida em uma TStringList.

 program procoutlarge;
 {
     Copyright (c) 2004 by Marc Weustink
 
     This example is creeated in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 }
 
 uses
   Classes, Process, SysUtils;
 
 const
   READ_BYTES = 2048;
 
 var
   S: TStringList;
   M: TMemoryStream;
   P: TProcess;
   n: LongInt;
   BytesRead: LongInt;
 
 begin
   // Nós não podemos usar poWaitOnExit aqui visto que nós não
   // conhecemos o tamanho da saída. No Linux o tamanho do
   // pipe de saida é 2 kB. Se os dados da saída são maiores, nós
   // precisamos ler os dados. Isto não é possível visto que nós estamos
   // esperando. Deste modo nós recebemos um deadlock aqui.
   //
   // Uma Memorystream temporária é usada para armazenar a saida
 
   M := TMemoryStream.Create;
   BytesRead := 0;
 
   P := TProcess.Create(nil);
   P.CommandLine := 'ppc386 -va bogus.pp';
   P.Options := [poUsePipes];
   WriteLn('-- executando --');
   P.Execute;
   while P.Running do
   begin
     // Verifica se temos dependências
     M.SetSize(BytesRead + READ_BYTES);
 
     // tenta ler ela
     n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
     if n > 0
     then begin
       Inc(BytesRead, n);
       Write('.')
     end
     else begin
       // sem dados, espera 100 ms
       Sleep(100);
     end;
   end;
   // lê a última parte
   repeat
     // verifica se temos dependências
     M.SetSize(BytesRead + READ_BYTES);
     // try reading it
     n := P.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);
   WriteLn('-- executado --');
 
   S := TStringList.Create;
   S.LoadFromStream(M);
   WriteLn('-- número de linhas = ', S.Count, ' --');
   for n := 0 to S.Count - 1 do
   begin
     WriteLn('| ', S[n]);
   end;
   WriteLn('-- final --');
   S.Free;
   P.Free;
   M.Free;
 end.

Usando a entrada e saida de um TProcess

Veja o exemplo processemo no Lazarus-CCR SVN.

Dicas no uso de TProcess

Se você está criando um programa multi-plataforma, você pode mudar a linha de comando de acordo com o SO (Sistema Operacional), usando diretivas "{$IFDEF}s" and "{$ENDIF}s".

Exemplo:

 {...}
   AProcess:TProcess.Create(nil)
   {$IFDEF WIN32}
   AProcess.CommandLine := 'calc.exe'; //Calculadora do Windows
   {$ENDIF}
   {$IFDEF LINUX}
   AProcess.CommandLine := 'kcalc'; //Calculadora do KDE
   {$ENDIF}
   AProcess.Execute; //em alternativa, você pode usar AProcess.Active:=True
 {...}


Exemplo de "conversa" com um processo aspell

Dentro do código-fonte do pasdoc você pode encontrar duas units que executam 'spell-checking' por uma conversa com o processo aspell em execução através de "pipes":

  • A unit PasDoc_ProcessLineTalk.pas implementa a classe TProcessLineTalk, descendente de TProcess, que pode ser facilmente usada para conversar com qualquer processo em uma base de linha-por-linha.
  • A unit PasDoc_Aspell.pas implementa a classe TAspellProcess, que executa 'spell-checking' pela utilização de uma instância subjacente TProcessListTalk para executar aspell e comunicar com o processo aspell em execução.

Ambas as units são um pouco independentes do resto dos fontes pasdoc, assim elas pode servir como exemplos reais da utilização de TProcess para executar comunicação através de pipes com outros programas.