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 AsyncProcess; 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 Execute; 107 108 if poUsePipes in Options then 109 FPipeHandler := AddPipeEventHandler(Output.Handle, @HandlePipeInput, 0); 110 FProcessHandler := AddProcessEventHandler(ProcessHandle, @HandleProcessTermination, 0); 111end; 112 113procedure Register; 114begin 115 RegisterComponents('System',[TAsyncProcess]); 116end; 117 118end. 119