Sign in Join
Wiki copytemporary

Executing External Programs/it: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Executing External Programs/it

OldNewLine
1+## Introduzione
2+
3+Ci sono diversi modi di eseguire un programma esterno, ma questo articolo ne esamina solo uno: [[doc:fcl/process/tprocess.html|TProcess]].
4+
5+Se solitamente usi **ShellExecute** e/o **WinExec** in Delphi, puoi iniziare ad usare TProcess come un'alternativa in FPC/Lazarus (vale anche se usi Lazarus in Linux, perché TProcess è cross-platform).
6+
7+**Nota:** FPC/Lazarus supporta **ShellExecute** e/o **WinExec**, ma questo supporto è solo in Win32. Se vuoi programmare 'cross-platform', allora usa TProcess, è la miglior scelta!
8+
9+## SysUtils.ExecuteProcess
10+
11+Se non hai bisogno di 'pipes' né di altre forme di controllo, il sistema più semplice è quello di usare SysUtils.ExecuteProcess('/percorso/completo/al/file/binario',\['arg1','arg2'\]);
12+
13+## TProcess
14+
15+Puoi usare TProcess per lanciare programmi esterni. Alcuni vantaggi nell'uso di TProcess sono:
16+
17+- Piattaforma Indipendente
18+- Capacità di leggere da stdout e scrivere in stdin.
19+
20+Nota: TProcess non è un terminal/shell! Non puoi eseguire direttamente scripts or redirigere output usando operatori tipo "\|", "\>", "\<", "&" etc. E' possibile ottenere gli stessi risultati con TProcess usando Pascal; puoi vedere alcuni esempi più avanti.
21+
22+Importante: Devi specificare il percorso completo dell'eseguibile. Per esempio '/bin/cp' invece di 'cp'. Se il programma è nel percorso standard PATH allora puoi usare la funzione [[doc:lcl/fileutil/finddefaultexecutablepath.html|FindDefaultExecutablePath]] dalla unit [[doc:lcl/fileutil/index.html|FileUtil]] di LCL.
23+
24+### Un semplice esempio
25+
26+``` pascal
27+ // Questo è un programma dimostrativo che mostra come lanciare
28+ // un programma esterno.
29+ program launchprogram;
30+
31+ // Qui includiamo i files che hanno utilizzo funzionale
32+ // e le procedure che ci occorreranno.
33+ uses
34+ Classes, SysUtils, Process;
35+
36+ // Questa è la definizione della variabile "AProcess"
37+ // come una variabile di tipo "TProcess"
38+ var
39+ AProcess: TProcess;
40+
41+ // Qui è dove il nostro programma inizia
42+ begin
43+ // Adesso creeremo l'oggetto TProcess e
44+ // lo assegneremo alla variabile var AProcess.
45+ AProcess := TProcess.Create(nil);
46+
47+ // Diremo al nuovo AProcess quale è il comando da eseguire.
48+ // Usa il compilatore FreePascal
49+ AProcess.CommandLine := 'ppc386 -h';
50+
51+ // Definiremo una opzione per quando il programma
52+ // è in esecuzione. Questa opzione ci assicurerà che il nostro programma
53+ // non continuerà sin quando il programma che lanceremo
54+ // non sarà terminato. vvvvvvvvvvvvvv
55+ AProcess.Options := AProcess.Options + [poWaitOnExit];
56+
57+ // Adesso che AProcess sa qual'è la linea di comando
58+ // verrà lanciato.
59+ AProcess.Execute;
60+
61+ // Questo non avverrà sino a quando ppc386 non fermerà la sua esecuzione.
62+ AProcess.Free;
63+ end.
64+```
65+
66+Questo è quanto! Hai appena imparato come eseguire un programma esterno dall'interno del tuo programma.
67+
68+### Un esempio più elaborato
69+
70+Che bello!, ma come faccio a leggere l'Output di un programma che ho eseguito?
71+
72+Bene, sviluppiamo un po' il nostro esempio in modo da ottenere questo:
73+
74+``` pascal
75+ // Questo è un programma dimostrativo che mostra come
76+ // lanciare un programma esterno e leggere dal suo output.
77+ program launchprogram;
78+
79+ // Qui mettiamo i files che contengono funzioni utili
80+ // e le procedure di cui abbiamo bisogno.
81+ uses
82+ Classes, SysUtils, Process;
83+
84+ // Questa è la definizione della variabile "AProcess"
85+ // come variabile del tipo "TProcess"
86+ // Aggiungiamo anche una TStringList per memorizzare
87+ // i dati che leggeremo dall'output del programma.
88+ var
89+ AProcess: TProcess;
90+ AStringList: TStringList;
91+
92+ // Questo è l'inizio del programma
93+ begin
94+ // Ora creeremo l'oggetto TProcess, e lo
95+ // assegneremo alla variabile AProcess.
96+ AProcess := TProcess.Create(nil);
97+
98+ // Creazione dell'oggetto TStringList.
99+ AStringList := TStringList.Create;
100+
101+ // Diciamo al nuovo AProcess quale comando eseguire.
102+ // Utilizza il compilatore FreePascal
103+ AProcess.CommandLine := 'ppc386 -h';
104+
105+ // Definiamo un'opzione per il programma durante
106+ // l'esecuzione. Questa opzione garantisce che il nostro
107+ // programma rimane in attesa finché il programma che
108+ // abbiamo lanciato non si ferma. Gli diciamo anche che
109+ // vogliamo leggere l'output.
110+ AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
111+
112+ // Ora che AProcess qual'è la linea di comando
113+ // lo eseguiamo.
114+ AProcess.Execute;
115+
116+ // Quanto segue non viene eseguito finché ppc386 non
117+ // termina l'esecuzione.
118+
119+ // Ora leggiamo l'output del programma che abbiamo
120+ // appena eseguito all'interno della TStringList.
121+ AStringList.LoadFromStream(AProcess.Output);
122+
123+ // Salviamo l'output in un file.
124+ AStringList.SaveToFile('output.txt');
125+
126+ // Ora che il file è stato salvato, possiamo liberare
127+ // la TStringList e il TProcess.
128+ AStringList.Free;
129+ AProcess.Free;
130+ end.
131+```
132+
133+### Leggere output di grandi dimensioni
134+
135+Nel precedente esempio noi abbiamo aspettato fino all'uscita del programma. Quindi leggiamo, quello che il programma ha scritto nel suo output. Ma supponiamo che il programma scriva molti dati nell'output, il buffer si riempie e il programma richiamato aspetta sinché il buffer non viene letto. Ma il programma chiamante non legge dal buffer, sinché il programma chiamato non ha terminato. Avviene un blocco.
136+
137+Il seguente esempio quindi non usa poWaitOnExit, ma legge dall'output, mentre il programma è ancora in esecuzione. L'output è immagazzinato in un buffer di memoria, che potrà essere usato più tardi per leggere l'output all'interno di una TStringList.
138+
139+``` pascal
140+ program procoutlarge;
141+ {
142+ Copyright (c) 2004 by Marc Weustink
143+
144+ This example is creeated in the hope that it will be useful,
145+ but WITHOUT ANY WARRANTY; without even the implied warranty of
146+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
147+ }
148+
149+ uses
150+ Classes, Process, SysUtils;
151+
152+ const
153+ READ_BYTES = 2048;
154+
155+ var
156+ S: TStringList;
157+ M: TMemoryStream;
158+ P: TProcess;
159+ n: LongInt;
160+ BytesRead: LongInt;
161+
162+ begin
163+ // We cannot use poWaitOnExit here since we don't
164+ // know the size of the output. On Linux the size of the
165+ // output pipe is 2 kB. If the output data is more, we
166+ // need to read the data. This isn't possible since we are
167+ // waiting. So we get a deadlock here.
168+ //
169+ // A temp Memorystream is used to buffer the output
170+
171+ M := TMemoryStream.Create;
172+ BytesRead := 0;
173+
174+ P := TProcess.Create(nil);
175+ P.CommandLine := 'ppc386 -va bogus.pp';
176+ P.Options := [poUsePipes];
177+ WriteLn('-- executing --');
178+ P.Execute;
179+ while P.Running do
180+ begin
181+ // make sure we have room
182+ M.SetSize(BytesRead + READ_BYTES);
183+
184+ // try reading it
185+ n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
186+ if n > 0
187+ then begin
188+ Inc(BytesRead, n);
189+ Write('.')
190+ end
191+ else begin
192+ // no data, wait 100 ms
193+ Sleep(100);
194+ end;
195+ end;
196+ // read last part
197+ repeat
198+ // make sure we have room
199+ M.SetSize(BytesRead + READ_BYTES);
200+ // try reading it
201+ n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
202+ if n > 0
203+ then begin
204+ Inc(BytesRead, n);
205+ Write('.');
206+ end;
207+ until n <= 0;
208+ if BytesRead > 0 then WriteLn;
209+ M.SetSize(BytesRead);
210+ WriteLn('-- executed --');
211+
212+ S := TStringList.Create;
213+ S.LoadFromStream(M);
214+ WriteLn('-- linecount = ', S.Count, ' --');
215+ for n := 0 to S.Count - 1 do
216+ begin
217+ WriteLn('| ', S[n]);
218+ end;
219+ WriteLn('-- end --');
220+ S.Free;
221+ P.Free;
222+ M.Free;
223+ end.
224+```
225+
226+### Usare input e output di TProcess
227+
228+Vedi l'esempio dimostrativo in [Lazarus-CCR SVN](https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/examples/process).
229+
230+### Accorgimenti nell'uso di TProcess
231+
232+Se stai creando un programma multipiattaforma (cross-platform) , Puoi cambiare la linea di comando in base al Sistema Operativo , usando le direttive "{\$IFDEF}s" and "{\$ENDIF}s".
233+
234+Esempio:
235+
236+``` pascal
237+ {...}
238+ AProcess:TProcess.Create(nil)
239+ {$IFDEF WIN32}
240+ AProcess.CommandLine := 'calc.exe'; //Windows Calc
241+ {$ENDIF}
242+ {$IFDEF LINUX}
243+ AProcess.CommandLine := 'kcalc'; //KDE Calc
244+ {$ENDIF}
245+ AProcess.Execute; //in alternative, you can use AProcess.Active:=True
246+ {...}
247+```
248+
249+### Esempio di dialogo con il processo aspell
250+
251+All'interno di [pasdoc](http://pasdoc.sourceforge.net/) Codice sorgente puoi trovare due units che fanno spell-checking mediante "dialogo" con aspell in esecuzione attraverso pipes:
252+
253+- [PasDoc_ProcessLineTalk.pas unit](http://pasdoc.svn.sourceforge.net/viewvc/*checkout*/pasdoc/trunk/source/component/PasDoc_ProcessLineTalk.pas) implements TProcessLineTalk class, descendant of TProcess, that can be easily used to talk with any process on a line-by-line basis.
254+
255+- [PasDoc_Aspell.pas units](http://pasdoc.svn.sourceforge.net/viewvc/*checkout*/pasdoc/trunk/source/component/PasDoc_Aspell.pas) implements TAspellProcess class, that performs spell-checking by using underlying TProcessLineTalk instance to execute aspell and communicate with running aspell process.
256+
257+Entrambe le units sono indipendenti dal resto di pasdoc sorgente, cosi che esse possono servire come esempio reale dell'uso di TProcess per eseguire e comunicare attraverso pipes con altri programmi.
258+
259+---
260+*From the Free Pascal wiki, page "Executing External Programs/it", 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](/wiki-contact).*

Back to history