Sign in Join
Wiki copytemporary

Executing External Programs/sk

Deutsch · English · Español · Français · Italiano · Nederlands · Polski · Português · Slovenčina · Русский · 中文(中国) · 日本語

Úvod

Je mnoho spôsobov ako spustiť externé programy. Zameriame sa na jeden z nich.

SysUtils.ExecuteProcess

najjednoduchší spôsob, ak nepotrebujete rúry (pipes) alebo žiadne formu ovládania je jednoducho použiť

pascal
 SysUtils.ExecuteProcess('/full/path/to/binary',['arg1','arg2']);

TProcess

Môžete použiť TProcess na spustenie externých programov. Výhody tohoto spôsobu sú:

Poznámka: TProcess nie je terminal/shell! Nemôžete priamo spustiť alebo presmerovať výstup pomocou operátorov ako "|", ">", "<", "&" atď. Možno získať rovnaký výsledok s TProcess pomocou Pascal, príklady nasledujú...

Jednoduchý príklad

pascal
 // Toto je ukážkový program ktorý vám ukáže ako
 // spustiť externý program.
 program launchprogram;
 
 // Tu si "použijeme" unity ktoré budeme potrebovať
 uses 
   Classes, SysUtils, Process;
 
 // Toto je definícia premennej APRocess
 // typu "TProcess"
 var 
   AProcess: TProcess;
 
 // Začiatok programu
 begin
   // Vytvoríme objekt TProcess
   // pridelíme ho do premennej AProcess
   AProcess := TProcess.Create(nil);
 
   // Povieme novému procesu aký príkaz má vykonať
   // Použime FPC prekladač
   AProcess.CommandLine := 'ppc386 -h';
 
   // Definujeme nastavenie pre spustenie.
   // Toto nastavenie zaručí že náš program
   // nebude pokračovať až kým sa proces neskončí
   AProcess.Options := AProcess.Options + [poWaitOnExit];
 
   // Teraz keď už proces vie čo má robiť
   // ho môžeme spustiť.
   AProcess.Execute;
 
   // Toto sa dosiahne až po skončení procesu.
   AProcess.Free;   
 end.

To je všetko! Práve ste sa naučili ako spustit externý program použitím TProcess.

To je všetko pekné, ale ako získam výstup spusteného programu? Tak sa na to pozrime, trochu rozšírime náš priklad.

Vylepšený príklad

pascal
 // Toto je ukážkový program ktorý vám ukáže ako
 // spustiť externý program.
 program launchprogram;
 
 // Tu si "použijeme" unity ktoré budeme potrebovať
 uses 
   Classes, SysUtils, Process;
 
 // Toto je definícia premennej APRocess
 // typu "TProcess"
 // Teraz pridáme aj TStringList aby sme
 // mohli uložiť výstup procesu.
 var 
   AProcess: TProcess;
   AStringList: TStringList;
 
 // Začiatok programu
 begin
   // Vytvoríme objekt TProcess
   // pridelíme ho do premennej AProcess
   AProcess := TProcess.Create(nil);
 
   // Vytvoríme TStringList a pridelíme ho
   AStringList := TStringList.Create;
 
   // Povieme novému procesu aký príkaz má vykonať
   // Použime FPC prekladač
   AProcess.CommandLine := 'ppc386 -h';
 
   // Definujeme nastavenie pre spustenie.
   // Toto nastavenie zaručí že náš program
   // nebude pokračovať až kým sa proces neskončí
   // Zároveň ho nastavíme tak, aby sme mohli
   // čítať výstup.
   AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
 
   // Teraz keď už proces vie čo má robiť
   // ho môžeme spustiť.
   AProcess.Execute;
   
   // Toto sa dosiahne až po skončení procesu.
 
   // Teraz načítame výstup programu
   // do TStringListu.
   AStringList.LoadFromStream(AProcess.Output);
   
   // Uložíme výstup do súboru
   AStringList.SaveToFile('output.txt');
 
   // Teraz keď je už výstup uložený
   // môžeme uvolniť objekty.
   AStringList.Free;
   AProcess.Free;   
 end.

Čítanie veľkého výstupu

V predchádzajúcom príklade sme čakali na ukončenie programu a potom sme čítali čo mal program zapísané do výstupu. Ale predstavte si, že program zapisuje na výstup veľké množstvo dát, rúra sa plní a volaný program čaká na jej vyprázdnenie (prečítanie). Ale volajúci program z rúry nečíta, pretože čaká na ukončenie volaného programu. Nastalo uviaznutie.

Takže nasledujúci príklad nepoužíva poWaitOnExit, ale číta z výstupu, zatiaľ čo program stále beží. Výstup je uchovávaný v pamäťovom streame, ktorý môže byť neskôr použitý na prečítanie výstupu do TStringList.

pascal
 program procoutlarge;
 {
     Copyright (c) 2004 by Marc Weustink
 
     Tento príklad je vytvorený v nádeji, že bude užitočný,
     ale BEZ AKEJKOĽVEK ZÁRUKY; dokonca bez implicitnej záruky 
     MERCHANTABILITY alebo 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
   // Nemôžeme tu použiť poWaitOnExit, lebo nepoznáme 
   // veľkosť výstupu. V Linuxe je veľkosť 
   // výstupnej rúry 2 kB. Ak je výstupných dátviac, 
   // musíme dáta prečítať. To však nie je možné, keďže 
   // sme čakajúci. Takže by tu nastalo uviaznutie.
   //
   // Na buferovanie výstupu použijeme dočasný Memorystream 
   
   M := TMemoryStream.Create;
   BytesRead := 0;
 
   P := TProcess.Create(nil);
   P.CommandLine := 'ppc386 -va bogus.pp';
   P.Options := [poUsePipes];
   WriteLn('-- executing --');
   P.Execute;
   while P.Running do
   begin          
     // overenie, že máme dosť priestoru
     M.SetSize(BytesRead + READ_BYTES);
     
     // skús ho prečítať
     n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
     if n > 0 
     then begin
       Inc(BytesRead, n);
       Write('.')
     end
     else begin     
       // žiadne dáta, počkať 100 ms
       Sleep(100); 
     end;
   end;
   // čítať poslednú časť
   repeat
     // overenie, že máme dosť priestoru
     M.SetSize(BytesRead + READ_BYTES);
     // skús ho prečítať
     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('-- executed --');
   
   S := TStringList.Create;
   S.LoadFromStream(M);
   WriteLn('-- linecount = ', S.Count, ' --');
   for n := 0 to S.Count - 1 do
   begin
     WriteLn('| ', S[n]);
   end;
   WriteLn('-- end --');
   S.Free;
   P.Free;
   M.Free;
 end.

Použitie vstupu a výstupu z TProcess

Viz príklad processdemo na Lazarus-CCR SVN.

Pokyny pre použitie TProcess

Ak vytvárate cez platformný program, môžete zmeniť príkazový riadok v závislosti na OS, pomocou direktív "{$IFDEF}s" a "{$ENDIF}s".

Príklad:

pascal
 {...}
   AProcess:TProcess.Create(nil)
   {$IFDEF WIN32}
   AProcess.CommandLine := 'calc.exe'; //Windows Calc
   {$ENDIF}
   {$IFDEF LINUX}
   AProcess.CommandLine := 'kcalc'; //KDE Calc
   {$ENDIF}
   AProcess.Execute; //in alternative, you can use AProcess.Active:=True
 {...}

Príklad komunikácie s procesom aspell

V zdrojovom kóde pasdoc môžete nájsť dve unity, ktoré vykonávajú kontrolu pravopisu komunikáciou s bežiacim procesom aspell cez rúry:

Obe jednotky sú vcelku nezávislé od zvyšku zdrojového kódu pasdoc, takže môžu poslúžiť ako príklady skutočného použitia TProcess na spustenie a komunikáciu s inými programmi cez rúry.


From the Free Pascal wiki, page "Executing External Programs/sk", as it stood on 2020-02-14 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 3, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.