Sign in Join
Wiki copytemporary

Executing External Programs/fr: what changed

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

Title: Executing External Programs/fr

OldNewLine
1+## Introduction
2+
3+Il y a différentes manière de lancer un programme externe, mais nous ne nous concentrerons que sur une seule : [[doc:fcl/process/tprocess.html|TProcess]].
4+
5+Si vous utilisez toujours **ShellExecute** et/ou **WinExec** sous Delphi, vous devriez utilisez TProcess comme alternative sous FPC/Lazarus (cela fonctionne également si vous l'utilisez sous Linux, car TProcess est multi-plateforme).
6+
7+**Note :** FPC/Lazarus supporte **ShellExecute** et/ou **WinExec**, mais uniquement sous Win32. Si votre programme est multi-plateforme, utilisez TProcess, c'est la meilleure solution !
8+
9+## SysUtils.ExecuteProcess
10+
11+La manière la plus simple si vous n'avez pas besoin de pipes ou toute forme de contrôle est d'utiliser simplement SysUtils.ExecuteProcess('/full/path/to/binary',\['arg1','arg2'\]);
12+
13+## TProcess
14+
15+Vous pouvez utiliser TProcess pour lancer un programme externe à votre application. Le principal intérêt d'utiliser TProcess est qu'il est :
16+
17+- Indépendant de la plateforme
18+- Capable de lire les entrées sorties standards (stdin, stdout).
19+
20+### Un exemple simple
21+
22+``` pascal
23+ // This is a demo program that shows how to launch
24+ // an external program.
25+ program launchprogram;
26+
27+ // Here we include files that have useful functions
28+ // and procedures we will need.
29+ uses
30+ Classes, SysUtils, Process;
31+
32+ // This is defining the var "AProcess" as a variable
33+ // of the type "TProcess"
34+ var
35+ AProcess: TProcess;
36+
37+ // This is where our program starts to run
38+ begin
39+ // Now we will create the TProcess object, and
40+ // assign it to the var AProcess.
41+ AProcess := TProcess.Create(nil);
42+
43+ // Tell the new AProcess what the command to execute is.
44+ // Let's use the FreePascal compiler
45+ AProcess.CommandLine := 'ppc386 -h';
46+
47+ // We will define an option for when the program
48+ // is run. This option will make sure that our program
49+ // does not continue until the program we will launch
50+ // has stopped running. vvvvvvvvvvvvvv
51+ AProcess.Options := AProcess.Options + [poWaitOnExit];
52+
53+ // Now that AProcess knows what the commandline is
54+ // we will run it.
55+ AProcess.Execute;
56+
57+ // This is not reached until ppc386 stops running.
58+ AProcess.Free;
59+ end.
60+```
61+
62+C'est tout ! Vous venez d'apprendre à lancer un programme externe depuis votre application.
63+
64+### Un exemple amélioré
65+
66+C'est bien gentil tout ça, mais comment puis je lire la sortie d'un programme que je viens de lancer ?
67+
68+Bien, étendons juste un peu notre exemple :
69+
70+``` pascal
71+ // Ceci est un programme de démonstration qui montre
72+ // comment lancer un programme externe et lire sa sortie
73+ program launchprogram;
74+
75+ // Ici on inclue les fichiers qui ont les fonctions et procédures
76+ // dont nous avons besoin
77+ uses
78+ Classes, SysUtils, Process;
79+
80+ // Ceci définit la variable "AProcess" comment variable
81+ // de type "TProcess". On ajoute aussi une TStringList
82+ // pour stocker les données de la sortie programme.
83+ var
84+ AProcess: TProcess;
85+ AStringList: TStringList;
86+
87+ // Le programme commence ici.
88+ begin
89+ // On créé l'objet TProcess,
90+ // et on l'assigne à la variable AProcess
91+ AProcess := TProcess.Create(nil);
92+
93+ // On créé l'objet TStringList
94+ AStringList := TStringList.Create;
95+
96+ // On dit au nouveau AProcess quelle est la commande à exécuter
97+ // Utilisons le compilateur de FreePascal
98+ AProcess.CommandLine := 'ppc386 -h';
99+
100+ // Définissons une option pour indiquer que le programme est lancé.
101+ // Cela assurera que notre programme n'attend pas que le programme lancé soit terminé.
102+ // Nous allons aussi lui dire que nous voulons lire la sortie du fichier.
103+ AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
104+
105+ // Maintenent que AProcess sait quelle ligne de commande il doit lancer, go!
106+ AProcess.Execute;
107+
108+ // Le programme ne va pas plus loin tant que ppc386 n'a pas fini.
109+
110+ // Maintenant on lit dans la TStringList la sortie du programme.
111+ AStringList.LoadFromStream(AProcess.Output);
112+
113+ // Sauvegarde de la sortie dans un fichier
114+ AStringList.SaveToFile('output.txt');
115+
116+ // Maintenant on peut vider la TStringList et le TProcess.
117+ AStringList.Free;
118+ AProcess.Free;
119+ end.
120+```
121+
122+### Lire une grosse sortie
123+
124+Dans l'exemple précédent, nous attendons que le programme se termine. Au moment de la lecture, le programme à écrit sur la sortie. Mais supposons que le programme écrive beaucoup d'informations en sortie, le canal se saturera et nécessitera une lecture. Mais le programme appelant ne peu rien lire tant que le programme appelé n'est pas terminé. Une étreinte mortelle (deadlock) se produit alors.
125+
126+Le programme suivant, bien que n'utilisant pas poWaitOnExit, lit tout de même la sortie, tant que le programme est ouvert. La sortie est stockée dans un flux de mémoire, et peut être utilisé plus tard pour lire la sortie dans un TStringList.
127+
128+``` pascal
129+ program procoutlarge;
130+ {
131+ Copyright (c) 2004 by Marc Weustink
132+
133+ This example is creeated in the hope that it will be useful,
134+ but WITHOUT ANY WARRANTY; without even the implied warranty of
135+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
136+ }
137+
138+ uses
139+ Classes, Process, SysUtils;
140+
141+ const
142+ READ_BYTES = 2048;
143+
144+ var
145+ S: TStringList;
146+ M: TMemoryStream;
147+ P: TProcess;
148+ n: LongInt;
149+ BytesRead: LongInt;
150+
151+ begin
152+ // We cannot use poWaitOnExit here since we don't
153+ // know the size of the output. On Linux the size of the
154+ // output pipe is 2 kB. If the output data is more, we
155+ // need to read the data. This isn't possible since we are
156+ // waiting. So we get a deadlock here.
157+ //
158+ // A temp Memorystream is used to buffer the output
159+
160+ M := TMemoryStream.Create;
161+ BytesRead := 0;
162+
163+ P := TProcess.Create(nil);
164+ P.CommandLine := 'ppc386 -va bogus.pp';
165+ P.Options := [poUsePipes];
166+ WriteLn('-- executing --');
167+ P.Execute;
168+ while P.Running do
169+ begin
170+ // make sure we have room
171+ M.SetSize(BytesRead + READ_BYTES);
172+
173+ // try reading it
174+ n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
175+ if n > 0
176+ then begin
177+ Inc(BytesRead, n);
178+ Write('.')
179+ end
180+ else begin
181+ // no data, wait 100 ms
182+ Sleep(100);
183+ end;
184+ end;
185+ // read last part
186+ repeat
187+ // make sure we have room
188+ M.SetSize(BytesRead + READ_BYTES);
189+ // try reading it
190+ n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);
191+ if n > 0
192+ then begin
193+ Inc(BytesRead, n);
194+ Write('.');
195+ end;
196+ until n <= 0;
197+ if BytesRead > 0 then WriteLn;
198+ M.SetSize(BytesRead);
199+ WriteLn('-- executed --');
200+
201+ S := TStringList.Create;
202+ S.LoadFromStream(M);
203+ WriteLn('-- linecount = ', S.Count, ' --');
204+ for n := 0 to S.Count - 1 do
205+ begin
206+ WriteLn('| ', S[n]);
207+ end;
208+ WriteLn('-- end --');
209+ S.Free;
210+ P.Free;
211+ M.Free;
212+ end.
213+```
214+
215+### Employer l'entrée et la sortie d'un TProcess
216+
217+Voir l'exemple processdemo dans le [dépôt SVN de Lazarus-CCR](https://svn.sourceforge.net/svnroot/lazarus-ccr/examples/process).
218+
219+### Remarque sur l'utilisation de TProcess
220+
221+Si vous programmez une application multi-plateforme, vous pouvez changer la ligne de commande appelant l'application, en fonction du système d'exploitation. Pour cela utilisez {\$IFDEF} et {\$ENDIF}.
222+
223+Exemple :
224+
225+``` pascal
226+ {...}
227+ AProcess:TProcess.Create(nil)
228+ {$IFDEF WIN32}
229+ AProcess.CommandLine := 'calc.exe'; //Windows Calc
230+ {$ENDIF}
231+ {$IFDEF LINUX}
232+ AProcess.CommandLine := 'kcalc'; //KDE Calc
233+ {$ENDIF}
234+ AProcess.Execute; //in alternative, you can use AProcess.Active:=True
235+ {...}
236+```
237+
238+### Exemple de "Dialogue" avec le processus aspell
239+
240+Dans le code source de pasdoc [pasdoc](http://pasdoc.sourceforge.net/) vous trouverez deux unités qui analysent du texte par "dialogue" en lançant un processus aspell au travers de canaux :
241+
242+- [PasDoc_ProcessLineTalk.pas unit](http://cvs.sourceforge.net/viewcvs.py/*checkout*/pasdoc/pasdoc/source/component/PasDoc_ProcessLineTalk.pas) implémente la classe TProcessLineTalk, descendante de TProcess, qui permet un dialogue facile entre n'importe quel processus sur le principe du ligne par ligne.
243+
244+- [PasDoc_Aspell.pas units](http://cvs.sourceforge.net/viewcvs.py/*checkout*/pasdoc/pasdoc/source/component/PasDoc_Aspell.pas) implémente la classe de TAspellProcess, qui permet d'analyser du texte en utilisant l'exemple de TProcessLineTalk pour exécuter aspell et communiquer avec le processus en cours d'exécution d'aspell.
245+
246+Ces deux unités sont plutôt indépendantes du reste des sources de pasdoc, par conséquent elles peuvent servir d'exemples d'utilisation de TProcess en situation réelle pour exécuter et communiquer par les canaux avec un autre programme.
247+
248+---
249+*From the Free Pascal wiki, page "Executing External Programs/fr", 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