Difference between revisions of "Executing External Programs/sk"
(Aktualizácia obsahu stránky) |
m (TStringList nema Lines ani ReadFromStream ale LoadFromStream) |
||
Line 109: | Line 109: | ||
// Teraz načítame výstup programu | // Teraz načítame výstup programu | ||
// do TStringListu. | // do TStringListu. | ||
− | AStringList. | + | AStringList.LoadFromStream(AProcess.Output); |
// Uložíme výstup do súboru | // Uložíme výstup do súboru | ||
− | AStringList | + | AStringList.SaveToFile('output.txt'); |
// Teraz keď je už výstup uložený | // Teraz keď je už výstup uložený |
Revision as of 20:52, 28 March 2008
│
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) │
Ú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']);
</pascal>
TProcess
Môžete použiť TProcess na spustenie externých programov. Výhody tohoto spôsobu sú:
- Nezávislý na platforme
- Schopnosť čítať zo stdin a stdout.
- 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.
</pascal>
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.
</pascal>
Čí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.</pascal>
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 {...}</pascal>
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:
- PasDoc_ProcessLineTalk.pas unit implementuje triedu TProcessLineTalk, potomka TProcess, ktorú možno jednoducho použiť na komunikáciu s ktorýmkoľvek procesom na báze riadok-po-riadku.
- PasDoc_Aspell.pas unit implementuje triedu TAspellProcess, ktorá vykonáva kontrolu pravopisu pomocou základnej inštancie TProcessLineTalk pre spustenie aspell a komunikáciu so spusteným procesom aspell.
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.