source: tags/1.3.1/Packages/CevoComponents/AsyncProcess2.pas

Last change on this file was 290, checked in by chronos, 3 years ago
  • Modified: Use FreeAndNil instead of Free as defensive measure.
  • Modified: Use ihnerited without same method name specification.
File size: 3.2 KB
Line 
1{
2 /***************************************************************************
3 AsyncProcess.pp
4 ---------------
5 Initial Revision : Tue Dec 06 09:00:00 CET 2005
6
7
8 ***************************************************************************/
9
10 *****************************************************************************
11 This file is part of the Lazarus Component Library (LCL)
12
13 See the file COPYING.modifiedLGPL.txt, included in this distribution,
14 for details about the license.
15 *****************************************************************************
16}
17
18unit AsyncProcess2;
19
20{$mode objfpc}{$H+}
21
22interface
23
24uses
25 Classes, Process,
26 // LazUtils
27 FileUtil, UTF8Process,
28 // LCL
29 InterfaceBase, LCLIntf;
30
31type
32
33 { TAsyncProcess }
34
35 TAsyncProcess = class(TProcessUTF8)
36 private
37 FPipeHandler: PPipeEventHandler;
38 FProcessHandler: PProcessEventHandler;
39 FOnReadData: TNotifyEvent;
40 FOnTerminate: TNotifyEvent;
41 protected
42 function GetNumBytesAvailable: dword;
43 procedure HandlePipeInput(AData: PtrInt; AReasons: TPipeReasons);
44 procedure HandleProcessTermination(AData: PtrInt; AReason: TChildExitReason; AInfo: dword);
45 procedure UnhookPipeHandle;
46 procedure UnhookProcessHandle;
47 public
48 procedure Execute; override;
49 destructor Destroy; override;
50 property NumBytesAvailable: dword read GetNumBytesAvailable;
51 published
52 property OnReadData: TNotifyEvent read FOnReadData write FOnReadData;// You must read all the data in this event. Otherwise it is called again.
53 property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
54 end;
55
56procedure Register;
57
58implementation
59
60function TAsyncProcess.GetNumBytesAvailable: dword;
61begin
62 if not (poUsePipes in Options) then
63 Result := 0
64 else
65 Result := Output.NumBytesAvailable;
66end;
67
68destructor TAsyncProcess.Destroy;
69begin
70 UnhookProcessHandle;
71 UnhookPipeHandle;
72 inherited;
73end;
74
75procedure TAsyncProcess.UnhookProcessHandle;
76begin
77 if FProcessHandler <> nil then
78 RemoveProcessEventHandler(FProcessHandler);
79end;
80
81procedure TAsyncProcess.UnhookPipeHandle;
82begin
83 if FPipeHandler <> nil then
84 RemovePipeEventHandler(FPipeHandler);
85end;
86
87procedure TAsyncProcess.HandlePipeInput(AData: PtrInt; AReasons: TPipeReasons);
88begin
89 if prBroken in AReasons then
90 UnhookPipeHandle;
91 if prDataAvailable in AReasons then
92 if FOnReadData <> nil then
93 FOnReadData(Self);
94end;
95
96procedure TAsyncProcess.HandleProcessTermination(AData: PtrInt; AReason: TChildExitReason; AInfo: dword);
97begin
98 UnhookProcessHandle;
99 UnhookPipeHandle;
100 if FOnTerminate <> nil then
101 FOnTerminate(Self);
102end;
103
104procedure TAsyncProcess.Execute;
105begin
106 inherited;
107
108 if poUsePipes in Options then
109 FPipeHandler := AddPipeEventHandler(Output.Handle, @HandlePipeInput, 0);
110
111 // TODO: Unhook process handle for cases if Execute is executed multiple times
112 // Also unhook handler doesn't work on Linux for some reason https://bugs.freepascal.org/view.php?id=17807
113 if FProcessHandler <> nil then UnhookProcessHandle;
114
115 FProcessHandler := AddProcessEventHandler(ProcessHandle, @HandleProcessTermination, 0);
116end;
117
118procedure Register;
119begin
120 RegisterComponents('System',[TAsyncProcess]);
121end;
122
123end.
Note: See TracBrowser for help on using the repository browser.