Sign in Join
Wiki copytemporary

Revision 2 of 3, by WikiArchive on 11-4-2026. The page as it is now.

Executing External Programs/sk

Contents

Ú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ú:

pascal
**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 the Internet Archive kept it on 2022-12-09. 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.