Sign in Join
Wiki copytemporary

Executing External Programs/pl: what changed

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

OldNewLine
1-<div style="font-size:1.88em;margin:0.75em 0;">
2-
31Wykonywanie programów zewnętrznych
4-
5-</div>
62
73## Przegląd: Porównanie
84
95Istnieją różne sposoby dostępne w bibliotekach RTL, FCL i LCL dotyczące wykonywania zewnętrznego polecenia/procesu/programu.
106
117| Metoda | Biblioteka | Platformy | Pojedyncza linia | Cechy |
128|----|----|----|----|----|
139| [[Executing External Programs/pl|ExecuteProcess]] | RTL | Wieloplatformowy | Tak | Bardzo ograniczone, synchroniczne. |
1410| [[Executing External Programs/pl|ShellExecute]] | WinAPI | Tylko MS Windows | Tak | Wiele. Może uruchamiać programy z podwyższonymi uprawnieniami administratora. |
1511| [[Executing External Programs/pl|fpsystem, fpexecve]] | Unix | Tylko Unix | | |
1612| [[Executing External Programs/pl|TProcess]] | FCL | Wieloplatformowy | Nie | Pełny. |
1713| [[Executing External Programs/pl|RunCommand]] | FCL | Wieloplatformowy **Wymaga FPC 2.6.2+** | Tak | Obejmuje typowe użycie TProcess. |
1814| [[Executing External Programs/pl|OpenDocument]] | LCL | Wieloplatformowy | Tak | Tylko otwarty dokument. Dokument otworzy się z aplikacją powiązaną z podanym typem dokumentu. |
1915
2016## (Proces.)RunCommand
2117
2218- Odnośnik do [RunCommand](http://www.freepascal.org/docs-html/fcl/process/runcommand.html)
2319- Odnośnik do [RunCommandInDir](http://www.freepascal.org/docs-html/fcl/process/runcommandindir.html)
2420
2521W FPC 2.6.2 niektóre funkcje pomocnicze dla TProcess zostały dodane do modułu process w oparciu o wrappery (funkcje lub klasy opakowujące) używane w projekcie [[Projects using Lazarus|fpcup]]. Te funkcje są przeznaczone do użytku podstawowego i pośredniego, i mogą przechwytywać dane wyjściowe do pojedynczego ciągu string i w pełni obsługiwać duże dane wyjściowe.
2622
2723Prosty przykład to:
2824
2925``` pascal
3026program project1;
3127
3228{$mode objfpc}{$H+}
3329
3430uses
3531 Process;
3632
3733var
3834 s : ansistring;
3935
4036begin
4137
4238if RunCommand('/bin/bash',['-c','echo $PATH'],s) then
4339 writeln(s);
4440
4541end.
4642```
4743
4844Zauważ jednak, że nie wszystkie „wbudowane” polecenia powłoki (np. aliasy) działają, ponieważ aliasy domyślnie nie są rozwijane w powłokach nieinteraktywnych, a .bashrc nie jest odczytywany przez powłoki nieinteraktywne, chyba że ustawisz zmienną środowiskową BASH_ENV. tak więc poniższy przykąłd nie daje żadnych danych wyjściowych:
4945
5046``` pascal
5147program project2;
5248
5349{$mode objfpc}{$H+}
5450
5551uses
5652 Process;
5753
5854var
5955 s : ansistring;
6056
6157begin
6258
6359if RunCommand('/bin/bash',['-c','alias'],s) then
6460 writeln(s);
6561
6662end.
6763```
6864
6965Przeciążony wariant RunCommand zwraca kod wyjścia programu. RunCommandInDir uruchamia polecenie w innym katalogu (ustawia p.CurrentDirectory):
7066
7167``` pascal
7268function RunCommandIndir(const curdir:string;const exename:string;const commands:array of string;var outputstring:string; var exitstatus:integer): integer;
7369function RunCommandIndir(const curdir:string;const exename:string;const commands:array of string;var outputstring:string): boolean;
7470function RunCommand(const exename:string;const commands:array of string;var outputstring:string): boolean;
7571```
7672
7773W **FPC 3.2.0+** RunCommand otrzymał dodatkowe warianty, które pozwalają nadpisać TProcessOptions i WindowOptions.
7874
7975### Rozszerzenia RunCommand
8076
8177W **FPC 3.2.0+** implementacja RunCommand została uogólniona i ponownie zintegrowana z TProcess, aby umożliwić szybszą budowę własnych wariantów. Jako przykład wariant RunCommand z limitem czasu:
8278
8379``` pascal
8480
8581{$mode delphi}
8682uses classes, sysutils, process, dateutils;
8783type
8884 { TProcessTimeout }
8985 TProcessTimeout = class(TProcess)
9086 public
9187 timeoutperiod: TTime;
9288 timedout : boolean;
9389 started : TDateTime;
9490 procedure LocalnIdleSleep(Sender,Context : TObject;status:TRunCommandEventCode;const message:string);
9591 end;
9692
9793procedure TProcessTimeout.LocalnIdleSleep(Sender,Context : TObject;status:TRunCommandEventCode;const message:string);
9894begin
9995 if status=RunCommandIdle then
10096 begin
10197 if (now-started)>timeoutperiod then
10298 begin
10399 timedout:=true;
104100 Terminate(255);
105101 exit;
106102 end;
107103 sleep(RunCommandSleepTime);
108104 end;
109105end;
110106
111107function RunCommandTimeout(const exename:TProcessString;const commands:array of TProcessString;out outputstring:string; Options : TProcessOptions = [];SWOptions:TShowWindowOptions=swoNone;timeout:integer=60):boolean;
112108Var
113109 p : TProcessTimeout;
114110 i,
115111 exitstatus : integer;
116112 ErrorString : String;
117113begin
118114 p:=TProcessTimeout.create(nil);
119115 p.OnRunCommandEvent:=p.LocalnIdleSleep;
120116 p.timeoutperiod:=timeout/SecsPerDay;
121117 if Options<>[] then
122118 P.Options:=Options - [poRunSuspended,poWaitOnExit];
123119 p.options:=p.options+[poRunIdle]; // potrzebne do uruchomienia zdarzenia RUNIDLE. Zobacz Zmiany Użytkownika dla wersji 3.2.0
124120
125121 P.ShowWindow:=SwOptions;
126122 p.Executable:=exename;
127123 if high(commands)>=0 then
128124 for i:=low(commands) to high(commands) do
129125 p.Parameters.add(commands[i]);
130126 p.timedout:=false;
131127 p.started:=now;
132128 try
133129 // główna pętla wariantów runcommand(), pierwotnie oparta na scenariuszu "dużego wyjścia" na wiki, ale stale rozwijana przez 5 lat.
134130 result:=p.RunCommandLoop(outputstring,errorstring,exitstatus)=0;
135131 if p.timedout then
136132 result:=false;
137133 finally
138134 p.free;
139135 end;
140136 if exitstatus<>0 then result:=false;
141137end;
142138
143139// przykładowe zastosowanie:
144140
145141var
146142 s : string;
147143begin
148144 for s in FileList do
149145 begin
150146 if not RunCommandTimeout('someexe',['-v',s,'--output','dest\'+s],err,[],swoNone,60) then
151147 begin
152148 // nie udało się uruchomić lub upłynął limit czasu. np. movefile() do "wadliwego" katalogu.
153149 end
154150 else
155151 begin
156152 // ok, plik przeniesiony do "dobrego" katalogu.
157153 end;
158154 end;
159155end;
160156```
161157
162158## SysUtils.ExecuteProcess
163159
164160(Wieloplatformowy)\
165161Pomimo wielu ograniczeń, najprostszym sposobem uruchomienia programu (modalnego, bez potoków lub jakiejkolwiek formy sterowania) jest po prostu użycie:
166162
167163``` pascal
168164SysUtils.ExecuteProcess(UTF8ToSys('/full/path/to/binary'), '', []);
169165```
170166
171167Proces wywołujący działa synchronicznie: „zawiesza się” do momentu zakończenia działania zewnętrznego programu — ale może to być przydatne, jeśli wymagasz od użytkownika wykonania czegoś przed kontynuowaniem pracy w aplikacji. Aby uzyskać bardziej wszechstronne podejście, zapoznaj się z sekcją dotyczącą preferowanego międzyplatformowego **RunCommand** lub innej funkcjonalności **TProcess**, lub jeśli chcesz obsługiwać tylko system Windows, możesz użyć **ShellExecute**.
172168
173169- Odniesienie do [ExecuteProcess](http://www.freepascal.org/docs-html/rtl/sysutils/executeprocess.html)
174170
175171## MS Windows: CreateProcess, ShellExecute i WinExec
176172
177173> **Note:** Chociaż FPC/Lazarus obsługuje **CreateProcess**, **ShellExecute** i/lub **WinExec**, ta obsługa jest dostępna tylko w Win32/64. Jeśli Twój program jest wieloplatformowy, rozważ użycie **RunCommand** lub **TProcess**.
178174
179175> **Note:** WinExec to 16-bitowe wywołanie, które od lat jest przestarzałe w interfejsie API systemu Windows. W ostatnich wersjach FPC generuje ostrzeżenie.
180176
181177**ShellExecute** to standardowa funkcja systemu MS Windows (ShellApi.h) z dobrą \[<http://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85>).aspx dokumentacją na MSDN\] (zwróć uwagę na ich komentarze na temat inicjalizacji COM, jeśli odkryjesz, że ta jest niewiarygodna).
182178
183179``` pascal
184180uses ..., ShellApi;
185181
186182// Proste jednowierszowe (ignorowanie zwracanych błędów):
187183if ShellExecute(0,nil, PChar('"C:\my dir\prog.exe"'),PChar('"C:\somepath\some_doc.ext"'),nil,1) =0 then;
188184
189185// Wykonaj plik wsadowy:
190186if ShellExecute(0,nil, PChar('cmd'),PChar('/c mybatch.bat'),nil,1) =0 then;
191187
192188// Otwórz okno poleceń w danym folderze:
193189if ShellExecute(0,nil, PChar('cmd'),PChar('/k cd \path'),nil,1) =0 then;
194190
195191// Otwórz adres URL strony internetowej w domyślnej przeglądarce za pomocą polecenia „start” (poprzez ukryte okno cmd):
196192if ShellExecute(0,nil, PChar('cmd'),PChar('/c start www.lazarus.freepascal.org/'),nil,0) =0 then;
197193
198194// lub przydatna procedura:
199195procedure RunShellExecute(const prog,params:string);
200196begin
201197 // parametry: ( Uchwyt, nil/'open'/'edit'/'find'/'explore'/'print', // 'open' nie zawsze jest potrzebny
202198 // path+prog, parametry, folder roboczy,
203199 // okno command 0=ukryte / 1=SW_SHOWNORMAL / 3=maks / 7=min) // dla stałych SW_ : uses ... Windows ...
204200 if ShellExecute(0,'open',PChar(prog),PChar(params),PChar(extractfilepath(prog)),1) >32 then; //sukces
205201 // zwracane wartości 0..32 są błędami
206202end;
207203```
208204
209205Istnieje również ShellExecuteExW jako wersja WideChar, a ShellExecuteExA to wersja AnsiChar.
210206
211207Opcja fMask może również używać SEE_MASK_DOENVSUBST lub SEE_MASK_FLAG_NO_UI lub SEE_MASK_NOCLOSEPROCESS itp.
212208
213209Jeśli w Delphi używałeś ShellExecute do **dokumentów** takich jak dokumenty Word lub adresy URL, spójrz na funkcje open* (OpenURL itp.) w module lclintf (zobacz sekcję [Zobacz także](https://wiki.lazarus.freepascal.org/Executing_External_Programs/pl#Zobacz_także) na dole tej strony).
214210
215211### Używanie ShellExecuteEx do podnoszenia uprawnień administratora
216212
217213Jeśli potrzebujesz uruchomić zewnętrzny program z podwyższonymi uprawnieniami administratora, możesz użyć metody **runas** z alternatywną funkcją ShellExecuteEx:
218214
219215``` pascal
220216uses ShellApi, ...;
221217
222218function RunAsAdmin(const Handle: Hwnd; const Path, Params: string): Boolean;
223219var
224220 sei: TShellExecuteInfoA;
225221begin
226222 FillChar(sei, SizeOf(sei), 0);
227223 sei.cbSize := SizeOf(sei);
228224 sei.Wnd := Handle;
229225 sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI;
230226 sei.lpVerb := 'runas';
231227 sei.lpFile := PAnsiChar(Path);
232228 sei.lpParameters := PAnsiChar(Params);
233229 sei.nShow := SW_SHOWNORMAL;
234230 Result := ShellExecuteExA(@sei);
235231end;
236232
237233procedure TFormMain.RunAddOrRemoveApplication;
238234begin
239235 // Przykład, który używa podwyższonego uprawnienia dla rundll, aby otworzyć Panel sterowania do programów i funkcji
240236 RunAsAdmin(FormMain.Handle, 'rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl', '');
241237end;
242238```
243239
244240## Unix fpsystem, fpexecve i shell
245241
246242Te funkcje są zależne od platformy.
247243
248244- Odniesienie do [fpsystem](http://www.freepascal.org/docs-html/rtl/unix/fpsystem.html)
249245- Odniesienie do [fpexecve](http://www.freepascal.org/docs-html/rtl/baseunix/fpexecve.html)
250246
251247Linux.Shell/Unix.Shell był odpowiednikiem fpsystem w wersji 1.0.x ze słabo zdefiniowaną obsługą błędów i po dekadzie deprecjacji został ostatecznie usunięty. Prawie we wszystkich przypadkach może być zastąpiony przez fpsystem, który obsługuje więcej standardów POSIX, takich jak obsługa błędów.
252248
253249## TProcess
254250
255251Możesz użyć TProcess do uruchamiania zewnętrznych programów. Niektóre z korzyści płynących z używania TProcess to:
256252
257253- Jest niezależny od platformy.
258254- Potrafi czytać ze standardowego wyjścia i zapisywać na standardowe wejście.
259255- Możliwe jest oczekiwanie na zakończenie polecenia lub pozwolenie na jego działanie podczas działania programu.
260256
261257Ważne informacje:
262258
263259- TProcess nie jest terminalem/powłoką! Nie możesz bezpośrednio wykonywać skryptów lub przekierowywać wyjścia za pomocą operatorów takich jak „\|”, „\>”, „\<”, „&” itp. Możliwe jest uzyskanie tych samych wyników za pomocą TProcess i za pomocą pascala - kilka przykładów poniżej.
264260- Przypuszczalnie w systemie Linux/Unix: **musisz** podać pełną ścieżkę do pliku wykonywalnego. Na przykład „/bin/cp” zamiast „cp”. Jeśli program znajduje się w standardowej PATH, możesz użyć funkcji [[doc:lcl/fileutil/finddefaultexecutablepath.html|FindDefaultExecutablePath]] z modułu [[doc:lcl/fileutil/index.html|FileUtil]] biblioteki LCL.
265261- W systemie Windows, jeśli polecenie znajduje się w ścieżce, nie musisz określać pełnej ścieżki.
266262- Odnośnik do [[doc:fcl/process/tprocess.html|TProcess]]
267263
268264### Najprostszy przykład
269265
270266Wiele typowych przypadków zostało przygotowanych w funkcjach [[Executing External Programs/pl|RunCommand]]. Zanim zaczniesz kopiować i wklejać poniższe przykłady, najpierw je sprawdź.
271267
272268### Prosty przykład
273269
274270Ten przykład (**który nie powinien być używany w środowisku produkcyjnym, patrz [[Executing External Programs/pl|Czytanie dużych ilości danych wyjściowych]] lub, lepiej, [[Executing External Programs/pl|RunCommand]]**) pokazuje tylko, jak uruchomić zewnętrzny program, nic więcej:
275271
276272``` pascal
277273// Jest to program demonstracyjny, który
278274// pokazuje, jak uruchomić zewnętrzny program.
279275program launchprogram;
280276
281277// Tutaj dołączamy moduły zawierające przydatne
282278// funkcje i procedury, których będziemy potrzebować.
283279uses
284280 Classes, SysUtils, Process;
285281
286282// Definiuje zmienną "AProcess" jako zmienną typu "TProcess"
287283var
288284 AProcess: TProcess;
289285
290286// Tu zaczyna działać nasz program
291287begin
292288 // Teraz utworzymy obiekt TProcess i przypiszemy go
293289 // do zmiennej AProcess.
294290 AProcess := TProcess.Create(nil);
295291
296292 // Powiedz nowemu AProcess, jakie jest polecenie do wykonania.
297293 // Użyjmy kompilatora Free Pascal (dokładniej wersji x64)
298294 // Lecz jeśli używasz kompilatora 32-bit zmień ppcx64 na ppc386
299295 AProcess.Executable:= 'ppcx64';
300296
301297 // Przekaż opcję -h razem z ppcx64, więc faktycznie wykonywane
302298 // jest polecenie 'ppcx64 -h':
303299 AProcess.Parameters.Add('-h');
304300
305301 // Zdefiniujemy opcję działającą, w czasie wykonywania programu.
306302 // Ta opcja sprawi, że nasz program nie będzie kontynuowany,
307303 // dopóki program zewnętrzy, który uruchomimy, nie przestanie działać.
308304 // /------------\
309305 AProcess.Options := AProcess.Options + [poWaitOnExit];
310306
311307 // Teraz pozwól AProcess uruchomić program zewnętrzny
312308 AProcess.Execute;
313309
314310 // Poniższy kod nie wykona się, dopóki ppcx64 nie przestanie działać.
315311 AProcess.Free;
316312end.
317313```
318314
319315Otóż ​​to! Właśnie nauczyłeś się uruchamiać zewnętrzny program z wnętrza własnego programu.
320316
321317### Ulepszony przykład (ale jeszcze niepoprawny)
322318
323319Wszystko fajnie, ale jak odczytać dane wyjściowe uruchomionego programu?
324320
325321Cóż, rozszerzmy nieco nasz przykład, jak poniżej: **Ten przykład jest prosty, więc możesz się z niego uczyć. Jednak nie używaj tego przykładu w kodzie produkcyjnym, ale użyj kodu z [[Executing External Programs/pl|Czytanie dużych ilości danych wyjściowych]].**
326322
327323``` pascal
328324// To jest
329325// WADLIWY
330326// program demonstracyjny, który pokazuje,
331327// jak uruchomić zewnętrzny program
332328// i odczytać z jego dane wyjściowe.
333329program launchprogram;
334330
335331// Tutaj dołączamy moduły zawierające przydatne
336332// funkcje i procedury, których będziemy potrzebować.
337333uses
338334 Classes, SysUtils, Process;
339335
340336// Definiuje zmienną "AProcess" jako zmienną typu "TProcess"
341337// Teraz także dodajemy TStringList do przechowywania danych
342338// odczytanych z wyjścia programu.
343339var
344340 AProcess: TProcess;
345341 AStringList: TStringList;
346342
347343// Tu zaczyna działać nasz program
348344begin
349345 // Teraz utworzymy obiekt TProcess i przypiszemy go
350346 // do zmiennej AProcess.
351347 AProcess := TProcess.Create(nil);
352348
353349 // Powiedz nowemu AProcess, jakie jest polecenie do wykonania.
354350 AProcess.Executable := '/usr/bin/ppcx64';
355351 AProcess.Parameters.Add('-h');
356352
357353 // Zdefiniujemy opcję działającą, w czasie wykonywania programu.
358354 // Ta opcja sprawi, że nasz program nie będzie kontynuowany,
359355 // dopóki program zewnętrzy, który uruchomimy, nie przestanie działać.
360356 // Dodatkowo teraz powiemy mu, że chcemy odczytać dane wyjściowe.
361357 // /------------|-----------\
362358 AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
363359
364360 // Teraz, gdy AProcess wie, jaki jest wiersz poleceń, można go uruchomić.
365361 AProcess.Execute;
366362
367363 // Po zakończeniu AProcess zostanie wykonana reszta programu.
368364
369365 // Teraz odczytaj wynik działania programu, za pomocą TStringList.
370366 AStringList := TStringList.Create;
371367 AStringList.LoadFromStream(AProcess.Output);
372368
373369 // Zapisz dane wyjściowe do pliku i zwolnij obiekt AStringList.
374370 AStringList.SaveToFile('output.txt');
375371 AStringList.Free;
376372
377373 // Teraz, gdy dane wyjściowe z procesu są przetworzone, także można je zwolnić.
378374 AProcess.Free;
379375end.
380376```
381377
382378### Czytanie dużych ilości danych wyjściowych
383379
384380W poprzednim przykładzie czekaliśmy, aż program się zakończy. Następnie czytaliśmy, co program zapisał na swoim wyjściu.
385381
386382Załóżmy, że program zapisuje dużo danych na wyjściu. Następnie potok wyjściowy zapełnia się i wywoływany program czeka, aż potok zostanie odczytany.
387383
388384Ale program wywołujący nie czyta z niego, dopóki wywoływany program się nie zakończy. Następuje impas.
389385
390386Poniższy przykład nie używa zatem poWaitOnExit, ale odczytuje dane wyjściowe, gdy program jest nadal uruchomiony. Dane wyjściowe są przechowywane w strumieniu pamięci, który można później wykorzystać do odczytania danych wyjściowych do TStringList.
391387
392388Jeśli chcesz odczytać dane wyjściowe z procesu zewnętrznego i nie możesz użyć RunCommand, jest to kod, który powinien być podstawą do użytku produkcyjnego. Jeśli używasz **FPC 3.2.0+**, parametryzowalna forma tej pętli jest dostępna jako metoda **RunCommandLoop** w TProcess. Zdarzenie **OnRunCommandEvent** można podłączyć, aby dalej modyfikować zachowanie.
393389
394390``` pascal
395391program LargeOutputDemo;
396392
397393{$mode objfpc}{$H+}
398394
399395uses
400396 Classes, SysUtils, Process; // Process to moduł, który zawiera TProcess
401397
402398const
403399 BUF_SIZE = 2048; // Rozmiar bufora do odczytu danych wyjściowych w porcjach
404400
405401var
406402 AProcess : TProcess;
407403 OutputStream : TStream;
408404 BytesRead : longint;
409405 Buffer : array[1..BUF_SIZE] of byte;
410406
411407begin
412408 // Skonfiguruj proces; jako przykład używane jest rekurencyjne przeszukiwanie
413409 // katalogów, ponieważ zwykle skutkuje to dużą ilością danych.
414410 AProcess := TProcess.Create(nil);
415411
416412 // Polecenia dla Windows i *nix są różne, stąd dyrektywy $IFDEF
417413 {$IFDEF Windows}
418414 // W systemie Windows polecenie dir nie może być użyte bezpośrednio, ponieważ jest to
419415 // wbudowane polecenie powłoki. Dlatego potrzebny jest cmd.exe i dodatkowe parametry.
420416 AProcess.Executable := 'c:\windows\system32\cmd.exe';
421417 AProcess.Parameters.Add('/c');
422418 AProcess.Parameters.Add('dir /s c:\windows');
423419 {$ENDIF Windows}
424420
425421 {$IFDEF Unix}
426422 AProcess.Executable := '/bin/ls';
427423
428424 {$IFDEF Darwin}
429425 AProcess.Parameters.Add('-recursive');
430426 AProcess.Parameters.Add('-all');
431427 {$ENDIF Darwin}
432428
433429 {$IFDEF Linux}
434430 AProcess.Parameters.Add('--recursive');
435431 AProcess.Parameters.Add('--all');
436432 {$ENDIF Linux}
437433
438434 {$IFDEF FreeBSD}
439435 AProcess.Parameters.Add('-R');
440436 AProcess.Parameters.Add('-a');
441437 {$ENDIF FreeBSD}
442438
443439 AProcess.Parameters.Add('-l');
444440 {$ENDIF Unix}
445441
446442 // Aby można było przechwycić dane wyjściowe, należy użyć opcji procesu poUsePipes.
447443 // Nie można użyć opcji procesu poWaitOnExit, ponieważ zablokuje to program główny,
448444 // uniemożliwiając mu odczytanie danych wyjściowych procesu zewnętrznego.
449445 AProcess.Options := [poUsePipes];
450446
451447 // Uruchom proces (uruchom polecenie dir dla Windows lub ls dla Linux/Unix)
452448 AProcess.Execute;
453449
454450 // Utwórz obiekt strumienia, w którym będą przechowywane wygenerowane dane wyjściowe.
455451 // Może to być również strumień plikowy do bezpośredniego zapisywania danych wyjściowych na dysku.
456452 OutputStream := TMemoryStream.Create;
457453
458454 // Wszystkie wygenerowane dane wyjściowe z AProcess są odczytywane w pętli,
459455 // dopóki nie będzie dostępnych więcej danych
460456 repeat
461457 // Pobierz nowe dane z procesu do maksymalnego rozmiaru buforu, który został przydzielony.
462458 // Zauważ, że wszystkie wywołania Read(...) będą blokowane z wyjątkiem ostatniego, które zwraca 0 (zero).
463459 BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
464460
465461 // Bajty, które zostały odczytane, dodaj do strumienia w celu późniejszego wykorzystania
466462 OutputStream.Write(Buffer, BytesRead)
467463
468464 until BytesRead = 0; // Zakończ pętlę, jeśli nie ma więcej danych
469465
470466 // Proces się zakończył, więc można go posprzątać
471467 AProcess.Free;
472468
473469 // Teraz, gdy wszystkie dane zostały odczytane, można z nich korzystać;
474470 // na przykład po to, by zapisać je do pliku na dysku
475471 with TFileStream.Create('output.txt', fmCreate) do
476472 begin
477473 OutputStream.Position := 0; // Wymagane, aby upewnić się, że wszystkie dane będą kopiowane od początku
478474 CopyFrom(OutputStream, OutputStream.Size);
479475 Free
480476 end;
481477
482478 // Lub dane mogą być wyświetlane na ekranie
483479 with TStringList.Create do
484480 begin
485481 OutputStream.Position := 0; // Wymagane, aby upewnić się, że wszystkie dane będą kopiowane od początku
486482 LoadFromStream(OutputStream);
487483 writeln(Text);
488484 writeln('--- Liczba linii = ', Count, '----');
489485 Free
490486 end;
491487
492488 // Sprzątanie
493489 OutputStream.Free;
494490end.
495491```
496492
497493Zauważ, że powyższe można również osiągnąć za pomocą RunCommand:
498494
499495``` pascal
500496var s: string;
501497...
502498RunCommand('c:\windows\system32\cmd.exe', ['/c', 'dir /s c:\windows'], s);
503499```
504500
505501### Korzystanie z wejścia i wyjścia TProcess
506502
507503Zobacz przykładowe demo procesu w [Lazarus-CCR SVN](https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/examples/process).
508504
509505### Wskazówki dotyczące korzystania z TProcess
510506
511507Podczas tworzenia programu wieloplatformowego nazwę pliku wykonywalnego specyficzną dla systemu operacyjnego można ustawić za pomocą dyrektyw „{\$IFDEF}” i „{\$ENDIF}”. Przykład:
512508
513509``` pascal
514510{...}
515511AProcess := TProcess.Create(nil)
516512
517513{$IFDEF WIN32}
518514 AProcess.Executable := 'calc.exe';
519515{$ENDIF}
520516
521517{$IFDEF LINUX}
522518 AProcess.Executable := FindDefaultExecutablePath('kcalc');
523519{$ENDIF}
524520
525521AProcess.Execute;
526522{...}
527523```
528524
529525### macOS pokazuje pakiet aplikacji na pierwszym planie
530526
531527Możesz uruchomić **pakiet aplikacji** przez TProcess, uruchamiając plik wykonywalny w pakiecie. Na przykład:
532528
533529``` pascal
534530 AProcess.Executable:='/Applications/iCal.app/Contents/MacOS/iCal';
535531```
536532
537533Spowoduje to uruchomienie *Kalendarza*, ale okno będzie znajdować się za bieżącą aplikacją. Aby uzyskać aplikację na pierwszym planie, możesz użyć narzędzia **open** z parametrem **-n**:
538534
539535``` pascal
540536 AProcess.Executable:='/usr/bin/open';
541537 AProcess.Parameters.Add('-n');
542538 AProcess.Parameters.Add('-a'); // opcjonalny: określa aplikację do użycia; przeszukuje tylko katalogi aplikacji
543539 AProcess.Parameters.Add('-W'); // opcjonalnie: open czeka, aż aplikacje, które otwiera (lub były już otwarte) zostaną zamknięte
544540 AProcess.Parameters.Add('Pages.app'); // dołączenie .app jest opcjonalne
545541```
546542
547543Jeśli Twoja aplikacja potrzebuje parametrów, możesz przekazać wraz z **open** parametr **--args**, po którym wszystkie dalsze parametry są przekazywane do aplikacji:
548544
549545``` pascal
550546 AProcess.Parameters.Add('--args');
551547 AProcess.Parameters.Add('argument1');
552548 AProcess.Parameters.Add('argument2');
553549```
554550
555551Zobacz także: [[macOS Open Sesame|macOS polecenie open]].
556552
557553### Uruchom oddzielny program
558554
559555Normalnie program uruchomiony przez twoją aplikację jest procesem potomnym i zostaje zabity, gdy twoja aplikacja zostanie zabita. Jeśli chcesz uruchomić samodzielny program, który nadal będzie działał, możesz użyć:
560556
561557``` pascal
562558var
563559 Process: TProcess;
564560 I: Integer;
565561begin
566562 Process := TProcess.Create(nil);
567563 try
568564 Process.InheritHandles := False;
569565 Process.Options := [];
570566 Process.ShowWindow := swoShow;
571567
572568 // Skopiuj domyślne zmienne środowiskowe, w tym zmienną DISPLAY, aby aplikacja GUI działała
573569 for I := 1 to GetEnvironmentVariableCount do
574570 Process.Environment.Add(GetEnvironmentString(I));
575571
576572 Process.Executable := '/usr/bin/gedit';
577573 Process.Execute;
578574 finally
579575 Process.Free;
580576 end;
581577end;
582578```
583579
584580### Przykład „rozmowy” z procesem aspell
585581
586582Wewnątrz kodu źródłowego [pasdoc](https://github.com/pasdoc/pasdoc/wiki) można znaleźć dwa moduły, które sprawdzają pisownię poprzez „rozmawianie” przez potoki z uruchomionym procesem aspell:
587583
588584- [Moduł PasDoc_ProcessLineTalk.pas](https://github.com/pasdoc/pasdoc/blob/master/source/component/PasDoc_ProcessLineTalk.pas) implementuje klasę TProcessLineTalk, potomka TProcess, która może być z łatwością używana do komunikacji z dowolnym procesem linia po linii.
589585
590586- [Moduł PasDoc_Aspell.pas](https://github.com/pasdoc/pasdoc/blob/master/source/component/PasDoc_Aspell.pas) implementuje klasę TAspellProcess, która sprawdza pisownię za pomocą bazowej instancji TProcessLineTalk do wykonania aspell i komunikacji z uruchomionym procesem aspell.
591587
592588Obydwa moduły są raczej niezależne od pozostałych źródeł pasdoc, więc mogą służyć jako rzeczywiste przykłady użycia TProcess do uruchamiania i komunikacji przez potoki z innym programem.
593589
594590### Zastępowanie operatorów powłoki, takich jak „\| \< \>”
595591
596592Czasami chcesz uruchomić bardziej skomplikowane polecenie, które przesyła dane do innego polecenia lub do pliku. Coś podobnego do
597593
598594``` pascal
599595ShellExecute('firstcommand.exe | secondcommand.exe');
600596```
601597
602598lub
603599
604600``` pascal
605601ShellExecute('dir > output.txt');
606602```
607603
608604Wykonanie tego za pomocą TProcess nie zadziała. tj:
609605
610606``` pascal
611607// to nie zadziała!
612608Process.CommandLine := 'firstcommand.exe | secondcommand.exe';
613609Process.Execute;
614610```
615611
616612#### Dlaczego używanie specjalnych operatorów do przekierowywania wyjścia nie działa?
617613
618614TProcess nie jest środowiskiem powłoki, tylko procesem. To nie dwa procesy, to tylko jeden. Możliwe jest jednak przekierowanie danych wyjściowych dokładnie tak, jak chcesz. Zobacz [[Executing External Programs/pl|następną sekcję]].
619615
620616### Jak przekierować wyjście za pomocą TProcess
621617
622618Możesz przekierować dane wyjściowe polecenia do innego polecenia, używając osobnej instancji TProcess dla **każdego** polecenia.
623619
624620Oto przykład, który wyjaśnia, jak przekierować dane wyjściowe jednego procesu do drugiego. Aby przekierować wyjście procesu do pliku/strumienia, zobacz przykład [[Executing External Programs/pl|Czytanie dużych ilości danych wyjściowych]].
625621
626622Możesz nie tylko przekierować „normalne” wyjście (znane również jako stdout), ale możesz także przekierować wyjście błędu (stderr), jeśli określisz opcję poStderrToOutPut, jak to widać w opcjach drugiego procesu.
627623
628624``` pascal
629625program Project1;
630626
631627uses
632628 Classes, sysutils, process;
633629
634630var
635631 FirstProcess,
636632 SecondProcess: TProcess;
637633 Buffer: array[0..127] of char;
638634 ReadCount: Integer;
639635 ReadSize: Integer;
640636begin
641637 FirstProcess := TProcess.Create(nil);
642638 SecondProcess := TProcess.Create(nil);
643639
644640 FirstProcess.Options := [poUsePipes];
645641 FirstProcess.Executable := 'pwd';
646642
647643 SecondProcess.Options := [poUsePipes,poStderrToOutPut];
648644 SecondProcess.Executable := 'grep';
649645 SecondProcess.Parameters.Add(DirectorySeparator+ ' -');
650646 // byłoby to to samo co "pwd | grep / -"
651647
652648 FirstProcess.Execute;
653649 SecondProcess.Execute;
654650
655651 while FirstProcess.Running or (FirstProcess.Output.NumBytesAvailable > 0) do
656652 begin
657653 if FirstProcess.Output.NumBytesAvailable > 0 then
658654 begin
659655 // upewnij się, że nie czytamy więcej danych niż przydzieliliśmy w buforze
660656 ReadSize := FirstProcess.Output.NumBytesAvailable;
661657 if ReadSize > SizeOf(Buffer) then
662658 ReadSize := SizeOf(Buffer);
663659 // teraz wczytaj dane wyjściowe do bufora
664660 ReadCount := FirstProcess.Output.Read(Buffer[0], ReadSize);
665661 // i zapisz bufor do drugiego procesu
666662 SecondProcess.Input.Write(Buffer[0], ReadCount);
667663
668664 // jeśli SecondProcess zapisuje dużo danych do swojego wyjścia,
669665 // powinniśmy odczytać te dane tutaj, aby zapobiec zakleszczeniu,
670666 // patrz poprzedni przykład "Czytanie dużych ilości danych wyjściowych"
671667 end;
672668 end;
673669 // Zamknij dane wejściowe w SecondProcess,
674670 // aby zakończyć przetwarzanie swoich danych
675671 SecondProcess.CloseInput;
676672
677673 // i poczekaj, aż się zakończy, lecz uważaj, jakie polecenie uruchamiasz,
678674 // ponieważ może się ono nie zakończyć, gdy jego dane wejściowe są zamknięte,
679675 // to następująca linia może zapętlić się w nieskończoność
680676 while SecondProcess.Running do
681677 Sleep(1);
682678 // Gotowe! Reszta programu jest tylko po to, aby przykład był bardziej 'użyteczny'
683679
684680 // użyjemy ponownie Buffer, aby wyprowadzić wyjście SecondProcess do *tego* programu stdout
685681 WriteLn('Rozpoczęcie wyjścia grep:');
686682 ReadSize := SecondProcess.Output.NumBytesAvailable;
687683 if ReadSize > SizeOf(Buffer) then
688684 ReadSize := SizeOf(Buffer);
689685 if ReadSize > 0 then
690686 begin
691687 ReadCount := SecondProcess.Output.Read(Buffer, ReadSize);
692688 WriteLn(Copy(Buffer,0, ReadCount));
693689 end
694690 else
695691 WriteLn('grep nie znalazł tego, czego szukaliśmy. ', SecondProcess.ExitStatus);
696692 WriteLn('Zakończenie wyjścia grep:');
697693
698694 // zwolnij obiekty naszych procesów
699695 FirstProcess.Free;
700696 SecondProcess.Free;
701697end.
702698```
703699
704700W ten sposób możesz przekierować dane wyjściowe z jednego programu do drugiego.
705701
706702#### Uwagi
707703
708704Ten przykład może wydawać się przesadny, ponieważ możliwe jest uruchamianie „skomplikowanych” poleceń przy użyciu powłoki przy pomocy TProcess, takich jak:
709705
710706``` pascal
711707Process.Commandline := 'sh -c "pwd | grep / -"';
712708```
713709
714710Ale nasz przykład jest bardziej wieloplatformowy, ponieważ nie wymaga modyfikacji, aby działać w systemie Windows lub Linux itp. Polecenie „sh” może, ale nie musi istnieć na twojej platformie i jest ogólnie dostępny tylko na platformach *nix. W naszym przykładzie mamy również większą elastyczność, ponieważ możesz czytać i zapisywać z/do wejścia, wyjścia i stderr każdego procesu z osobna, co może być bardzo korzystne dla twojego projektu.
715711
716712### Przekierowywanie wejścia i wyjścia oraz działanie z rootem
717713
718714Częstym problemem w systemach Unix (FreeBSD, macOS) i Linux jest to, że chcesz uruchomić jakiś program na koncie root (lub, bardziej ogólnie, na innym koncie użytkownika). Przykładem może być uruchomienie polecenia *ping*.
719715
720716Jeśli możesz użyć do tego sudo, możesz dostosować następujący przykład zaadaptowany z postu opublikowanego przez andymana na forum ([1](http://lazarus.freepascal.org/index.php/topic,14479.0.html)). Ten przykład uruchamia polecenie `ls` w katalogu `/root`, ale oczywiście można go dostosować.
721717
722718**Lepszym sposobem** na to jest użycie pakietu policykit, który powinien być dostępny we wszystkich najnowszych Linuksach. [Zobacz wątek na forum, aby uzyskać szczegółowe informacje.](http://lazarus.freepascal.org/index.php/topic,14479.0.html)
723719
724720Duże części tego kodu są podobne do wcześniejszego przykładu, ale pokazuje również, jak przekierować stdout i stderr procesu wywoływanego oddzielnie na stdout i stderr naszego własnego kodu.
725721
726722``` pascal
727723program rootls;
728724
729725{ Demonstracja użycia TProcess, przekierowania stdout/stderr do naszego stdout/stderr,
730726 wywoływania sudo w systemach FreeBSD/Linux/macOS i dostarczania danych wejściowych na stdin}
731727{$mode objfpc}{$H+}
732728
733729uses
734730 Classes,
735731 Math, {for min}
736732 Process;
737733
738734 procedure RunsLsRoot;
739735 var
740736 Proc: TProcess;
741737 CharBuffer: array [0..511] of char;
742738 ReadCount: integer;
743739 ExitCode: integer;
744740 SudoPassword: string;
745741 begin
746742 WriteLn('Please enter the sudo password:');
747743 Readln(SudoPassword);
748744 ExitCode := -1; //Zacznij od porażki, zobaczmy później, czy to zadziała
749745 Proc := TProcess.Create(nil); //Utwórz nowy proces
750746 try
751747 Proc.Options := [poUsePipes, poStderrToOutPut]; //Użyj potoków, aby przekierować stdin,stdout,stderr
752748 Proc.CommandLine := 'sudo -S ls /root'; //Uruchom ls /root jako root za pomocą sudo
753749 // -S powoduje, że sudo odczytuje hasło z stdin.
754750 Proc.Execute; //Uruchom to. sudo prawdopodobnie poprosi teraz o hasło
755751
756752 // wpisz hasło do stdin programu sudo:
757753 SudoPassword := SudoPassword + LineEnding;
758754 Proc.Input.Write(SudoPassword[1], Length(SudoPassword));
759755 SudoPassword := '%*'; // krótki string, mam nadzieję, że trochę pomiesza pamięć; uwaga: używanie PChars jest bardziej niezawodne
760756 SudoPassword := ''; // i sprawić, by program był nieco bezpieczniejszy przed węszeniem?!?
761757
762758 // główna pętla do odczytu wyjścia z stdout i stderr dla sudo
763759 while Proc.Running or (Proc.Output.NumBytesAvailable > 0) or
764760 (Proc.Stderr.NumBytesAvailable > 0) do
765761 begin
766762 // odczytaj stdout i zapisz do naszego stdout
767763 while Proc.Output.NumBytesAvailable > 0 do
768764 begin
769765 ReadCount := Min(512, Proc.Output.NumBytesAvailable); //Czytaj do bufora, nie więcej
770766 Proc.Output.Read(CharBuffer, ReadCount);
771767 Write(StdOut, Copy(CharBuffer, 0, ReadCount));
772768 end;
773769 // odczytaj stderr i zapisz do naszego stderr
774770 while Proc.Stderr.NumBytesAvailable > 0 do
775771 begin
776772 ReadCount := Min(512, Proc.Stderr.NumBytesAvailable); //Czytaj do bufora, nie więcej
777773 Proc.Stderr.Read(CharBuffer, ReadCount);
778774 Write(StdErr, Copy(CharBuffer, 0, ReadCount));
779775 end;
780776 end;
781777 ExitCode := Proc.ExitStatus;
782778 finally
783779 Proc.Free;
784780 Halt(ExitCode);
785781 end;
786782 end;
787783
788784begin
789785 RunsLsRoot;
790786end.
791787```
792788
793789Inne przemyślenia: Bez wątpienia wskazane byłoby sprawdzenie, czy sudo rzeczywiście pyta o hasło. Można to konsekwentnie sprawdzać, ustawiając zmienną środowiskową SUDO_PROMPT na coś, na co zwracamy uwagę podczas czytania stdout TProcess, unikając problemu związanego z różnymi znakami zachęty dla różnych lokalizacji. Ustawienie zmiennej środowiskowej powoduje wyczyszczenie wartości domyślnych (odziedziczonych z naszego procesu), więc w razie potrzeby musimy skopiować środowisko z naszego programu.
794790
795791### Używanie fdisk z sudo w systemie Linux
796792
797793Poniższy przykład pokazuje, jak uruchomić fdisk na komputerze z systemem Linux za pomocą polecenia sudo, aby uzyskać uprawnienia roota. **Uwaga: jest to tylko przykład i nie obejmuje dużej ilości danych na wyjściu.**
798794
799795``` pascal
800796program getpartitioninfo;
801797{Pierwotnie napisany przez użytkownika forum Lazarus wjackon153. Prosimy o kontakt w przypadku pytań, uwag itp.
802798Zmodyfikowan z fragmentu kodu Lazarusa na program FPC dla ułatwienia zrozumienia/zwięzłości przez BigChimp}
803799
804800Uses
805801 Classes, SysUtils, FileUtil, Process;
806802
807803var
808804 hprocess: TProcess;
809805 sPass: String;
810806 OutputLines: TStringList;
811807
812808begin
813809 sPass := 'yoursudopasswordhere'; // Musisz to zmienić na własne hasło sudo
814810 OutputLines:=TStringList.Create; //dla pewności warto zamknąć to w bloku try...finally...end
815811 // OutputLines został utworzony ... To samo dla hProcess.
816812
817813 // Poniższy przykład otworzy fdisk w tle i da nam informacje o partycjach
818814 // Ponieważ fdisk wymaga podwyższonych uprawnień, musimy przekazać
819815 // nasze hasło jako parametr do sudo za pomocą opcji -S, więc proces
820816 // poczeka, aż nasz program wyśle ​​nasze hasło do aplikacji sudo
821817
822818 hProcess := TProcess.Create(nil);
823819 // W systemach Linux/Unix/FreeBSD/macOS musimy podać pełną ścieżkę do naszego pliku wykonywalnego:
824820 hProcess.Executable := '/bin/sh';
825821 // Teraz dodajemy wszystkie parametry w wierszu poleceń:
826822 hprocess.Parameters.Add('-c');
827823 // Tutaj przesyłamy potokiem hasło do polecenia sudo, które następnie wykonuje fdisk -l:
828824 hprocess.Parameters.add('echo ' + sPass + ' | sudo -S fdisk -l');
829825 // Uruchom asynchronicznie (poczekaj na zakończenie procesu) i użyj potoków, abyśmy mogli odczytać potok wyjściowy
830826 hProcess.Options := hProcess.Options + [poWaitOnExit, poUsePipes];
831827 // Teraz wykonaj:
832828 hProcess.Execute;
833829
834830 // hProcess powinien teraz uruchomić zewnętrzny plik wykonywalny (ponieważ używamy poWaitOnExit).
835831 // Teraz możesz przetworzyć wyjście procesu (standardowe wyjście i standardowy błąd), np.:
836832 OutputLines.Add('stdout:');
837833 OutputLines.LoadFromStream(hprocess.Output);
838834 OutputLines.Add('stderr:');
839835 OutputLines.LoadFromStream(hProcess.Stderr);
840836 // Pokaż dane wyjściowe na ekranie:
841837 writeln(OutputLines.Text);
842838
843839 // Wyczyść, aby uniknąć wycieków pamięci:
844840 hProcess.Free;
845841 OutputLines.Free;
846842
847843 //Poniżej znajduje się kilka przykładów, jak widać, możemy przekazywać niedozwolone znaki, tak jak robimy to z terminala
848844 //Nawet jeśli przeczytałeś gdzie indziej, że nie możesz upewnić się tą metodą, to możesz :)
849845
850846 //hprocess.Parameters.Add('ping -c 1 www.google.com');
851847 //hprocess.Parameters.Add('ifconfig wlan0 | grep ' + QuotedStr('inet addr:') + ' | cut -d: -f2');
852848
853849 //Użycie QuotedStr() nie jest wymagane, chociaż zapewnia czystszy kod;
854850 //możesz użyć podwójnego cudzysłowu i mieć ten sam efekt.
855851
856852 //hprocess.Parameters.Add('glxinfo | grep direct');
857853
858854 // Ta metoda może być również używana do instalowania aplikacji z repozytorium:
859855
860856 //hprocess.Parameters.add('echo ' + sPass + ' | sudo -S apt-get install -y pkg-name');
861857
862858 end.
863859```
864860
865861### Parametry zawierające spacje (Zastępowanie cudzysłowów powłoki)
866862
867863W powłoce Linuksa możliwe jest pisanie cytowanych argumentów w następujący sposób:
868864
869865`gdb --batch --eval-command="info symbol 0x0000DDDD" myprogram`
870866
871867Polecenie GDB otrzyma 3 argumenty (oprócz pierwszego argumentu, który jest pełną ścieżką do pliku wykonywalnego):
872868
8738691. --batch
8748702. --eval-command=info symbol 0x0000DDDD
8758713. pełna ścieżka do myprogram
876872
877873Najlepszym rozwiązaniem, aby uniknąć skomplikowanego cytowania, jest przejście na TProcess.Parameters.Add zamiast ustawiania wiersza poleceń dla nietrywialnych przypadków, np.
878874
879875` AProcess.Executable:='/usr/bin/gdb';`\
880876` AProcess.Parameters.Add('--batch');`\
881877` AProcess.Parameters.Add('--eval-command=info symbol 0x0000DDDD'); // zwróć tutaj uwagę na brak cytowania`\
882878` AProcess.Parameters.Add('/home/me/myprogram');`
883879
884880Pamiętaj też, aby używać tylko pełne ścieżki.
885881
886882TProcess.Commandline obsługuje jednak tylko podstawowe cytowanie parametrów z cudzysłowami. Ujmij w apostrofy *cały* parametr zawierający spacje z podwójnymi cudzysłowami. Jak poniżej:
887883
888884`AProcess.CommandLine := '/usr/bin/gdb --batch "--eval-command=info symbol 0x0000DDDD" /home/me/myprogram';`
889885
890886Właściwość .CommandLine jest [przestarzała](http://bugs.freepascal.org/view.php?id=14446), a raporty o błędach do obsługi bardziej skomplikowanych przypadków cytowania nie będą akceptowane.
891887
892888## Alternatywy LCLIntf
893889
894890Czasami nie trzeba jawnie wywoływać zewnętrznego programu, aby uzyskać potrzebną funkcjonalność. Zamiast otwierać aplikację i określać dokument, który ma być z nią powiązany, po prostu poproś system operacyjny o otwarcie dokumentu i pozwól mu użyć domyślnej aplikacji powiązanej z tym typem pliku. Poniżej kilka przykładów.
895891
896892### Otwieranie dokumentu w domyślnej aplikacji
897893
898894W niektórych sytuacjach musisz otworzyć jakiś dokument/plik przy użyciu domyślnej aplikacji z nim powiązanej, zamiast uruchamiać konkretny program. To zależy od działającego systemu operacyjnego. Lazarus zapewnia niezależną od platformy procedurę OpenDocument, która zajmie się tym za Ciebie. Twoja aplikacja będzie nadal działać, nie czekając na zamknięcie procesu tworzenia dokumentu.
899895
900896``` pascal
901897uses LCLIntf;
902898...
903899OpenDocument('manual.pdf');
904900...
905901```
906902
907903- [[opendocument|Dokumentacja OpenDocument]]
908904
909905### Otwieranie strony web w domyślnej przeglądarce internetowej
910906
911907Aby to zrobić, po prostu przekaż wymagany adres URL. Przedrostek protokołu <http://> wydaje się w pewnych okolicznościach opcjonalny. Ponadto przekazanie nazwy pliku wydaje się dawać takie same wyniki jak OpenDocument()
912908
913909``` pascal
914910uses LCLIntf;
915911...
916912OpenURL('www.lazarus.freepascal.org/');
917913```
918914
919915Zobacz także:
920916
921917- [[OpenURL|Odnośnik do OpenURL]]
922918
923919Lub możesz użyć **TProcess** w taki sposób:
924920
925921``` pascal
926922uses Process;
927923
928924procedure OpenWebPage(URL: string);
929925// Możliwe, że musisz podać swój adres URL w cudzysłowiu np. "www.lazarus.freepascal.org"
930926var
931927 Browser, Params: string;
932928begin
933929 FindDefaultBrowser(Browser, Params);
934930 with TProcess.Create(nil) do
935931 try
936932 Executable := Browser;
937933 Params:=Format(Params, [URL]);
938934 Params:=copy(Params,2,length(Params)-2); // usuń znaki "", nowa wersja TProcess.Parameters robi to sama
939935 Parameters.Add(Params);
940936 Options := [poNoConsole];
941937 Execute;
942938 finally
943939 Free;
944940 end;
945941end;
946942```
947943
948944## Zobacz także
949945
950946- [dokumentacja TProcess](http://lazarus-ccr.sourceforge.net/docs/fcl/process/tprocess.html)
951947- [[opendocument|OpenDocument]]
952948- [[OpenURL]]
953949- [[TProcessUTF8]]
954950- [[TXMLPropStorage]]
955951- [[Webbrowser]]
956952
957953---
958954*From the Free Pascal wiki, page "Executing External Programs/pl", as it stood on 2023-11-03 after a change by Slawek, 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