123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- {
- This file is part of the Free Component library.
- Copyright (c) 2005 by Michael Van Canneyt, member of
- the Free Pascal development team
- Unit implementing one-way IPC between 2 processes
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit simpleipc;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils;
- Const
- MsgVersion = 1;
-
- //Message types
- mtUnknown = 0;
- mtString = 1;
-
- Type
- TMessageType = LongInt;
- TMsgHeader = Packed record
- Version : Byte;
- MsgType : TMessageType;
- MsgLen : Integer;
- end;
- TSimpleIPCServer = class;
- TSimpleIPCClient = class;
- { TIPCServerComm }
-
- TIPCServerComm = Class(TObject)
- Private
- FOwner : TSimpleIPCServer;
- Protected
- Function GetInstanceID : String; virtual; abstract;
- Procedure DoError(Msg : String; Args : Array of const);
- Procedure SetMsgType(AMsgType: TMessageType);
- Function MsgData : TStream;
- Public
- Constructor Create(AOwner : TSimpleIPCServer); virtual;
- Property Owner : TSimpleIPCServer read FOwner;
- Procedure StartServer; virtual; Abstract;
- Procedure StopServer;virtual; Abstract;
- Function PeekMessage(TimeOut : Integer) : Boolean;virtual; Abstract;
- Procedure ReadMessage ;virtual; Abstract;
- Property InstanceID : String read GetInstanceID;
- end;
- TIPCServerCommClass = Class of TIPCServerComm;
- { TSimpleIPC }
- TSimpleIPC = Class(TComponent)
- Private
- procedure SetActive(const AValue: Boolean);
- procedure SetServerID(const AValue: String);
- Protected
- FBusy: Boolean;
- FActive : Boolean;
- FServerID : String;
- Procedure DoError(Msg : String; Args : Array of const);
- Procedure CheckInactive;
- Procedure CheckActive;
- Procedure Activate; virtual; abstract;
- Procedure Deactivate; virtual; abstract;
- Property Busy : Boolean Read FBusy;
- Published
- Property Active : Boolean Read FActive Write SetActive;
- Property ServerID : String Read FServerID Write SetServerID;
- end;
- { TSimpleIPCServer }
- TSimpleIPCServer = Class(TSimpleIPC)
- private
- FGlobal: Boolean;
- FOnMessage: TNotifyEvent;
- FMsgType: TMessageType;
- FMsgData : TStream;
- function GetInstanceID: String;
- function GetStringMessage: String;
- procedure SetGlobal(const AValue: Boolean);
- Protected
- FIPCComm: TIPCServerComm;
- Function CommClass : TIPCServerCommClass; virtual;
- Procedure Activate; override;
- Procedure Deactivate; override;
- Procedure ReadMessage;
- Public
- Constructor Create(AOwner : TComponent); override;
- Destructor Destroy; override;
- Procedure StartServer;
- Procedure StopServer;
- Function PeekMessage(TimeOut : Integer; DoReadMessage : Boolean): Boolean;
- Property StringMessage : String Read GetStringMessage;
- Procedure GetMessageData(Stream : TStream);
- Property MsgType: TMessageType Read FMsgType;
- Property MsgData : TStream Read FMsgData;
- Property InstanceID : String Read GetInstanceID;
- Published
- Property Global : Boolean Read FGlobal Write SetGlobal;
- Property OnMessage : TNotifyEvent Read FOnMessage Write FOnMessage;
- end;
- { TIPCClientComm}
- TIPCClientComm = Class(TObject)
- private
- FOwner: TSimpleIPCClient;
- protected
- Procedure DoError(Msg : String; Args : Array of const);
- Public
- Constructor Create(AOwner : TSimpleIPCClient); virtual;
- Property Owner : TSimpleIPCClient read FOwner;
- Procedure Connect; virtual; abstract;
- Procedure Disconnect; virtual; abstract;
- Function ServerRunning : Boolean; virtual; abstract;
- Procedure SendMessage(MsgType : TMessageType; Stream : TStream);virtual;Abstract;
- end;
- TIPCClientCommClass = Class of TIPCClientComm;
-
- { TSimpleIPCClient }
- TSimpleIPCClient = Class(TSimpleIPC)
- Private
- FServerInstance: String;
- procedure SetServerInstance(const AValue: String);
- Protected
- FIPCComm : TIPCClientComm;
- Procedure Activate; override;
- Procedure Deactivate; override;
- Function CommClass : TIPCClientCommClass; virtual;
- Public
- Constructor Create(AOwner : TComponent); override;
- Destructor Destroy; override;
- Procedure Connect;
- Procedure Disconnect;
- Function ServerRunning : Boolean;
- Procedure SendMessage(MsgType : TMessageType; Stream: TStream);
- Procedure SendStringMessage(const Msg : String);
- Procedure SendStringMessage(MsgType : TMessageType; const Msg : String);
- Procedure SendStringMessageFmt(const Msg : String; Args : Array of const);
- Procedure SendStringMessageFmt(MsgType : TMessageType; const Msg : String; Args : Array of const);
- Property ServerInstance : String Read FServerInstance Write SetServerInstance;
- end;
- EIPCError = Class(Exception);
- Var
- DefaultIPCServerClass : TIPCServerCommClass = Nil;
- DefaultIPCClientClass : TIPCClientCommClass = Nil;
- resourcestring
- SErrServerNotActive = 'Server with ID %s is not active.';
- SErrActive = 'This operation is illegal when the server is active.';
- SErrInActive = 'This operation is illegal when the server is inactive.';
- implementation
- { ---------------------------------------------------------------------
- Include platform specific implementation.
- Should implement the CommClass method of both server and client component,
- as well as the communication class itself.
-
- This comes first, to allow the uses clause to be set.
- If the include file defines OSNEEDIPCINITDONE then the unit will
- call IPCInit and IPCDone in the initialization/finalization code.
-
- --------------------------------------------------------------------- }
- {$UNDEF OSNEEDIPCINITDONE}
- {$i simpleipc.inc}
- { ---------------------------------------------------------------------
- TIPCServerComm
- ---------------------------------------------------------------------}
- constructor TIPCServerComm.Create(AOwner: TSimpleIPCServer);
- begin
- FOwner:=AOWner;
- end;
- Procedure TIPCServerComm.DoError(Msg : String; Args : Array of const);
- begin
- FOwner.DoError(Msg,Args);
- end;
- Function TIPCServerComm.MsgData : TStream;
- begin
- Result:=FOwner.FMsgData;
- end;
- Procedure TIPCServerComm.SetMsgType(AMsgType: TMessageType);
- begin
- Fowner.FMsgType:=AMsgType;
- end;
- { ---------------------------------------------------------------------
- TIPCClientComm
- ---------------------------------------------------------------------}
-
- constructor TIPCClientComm.Create(AOwner: TSimpleIPCClient);
- begin
- FOwner:=AOwner;
- end;
- Procedure TIPCClientComm.DoError(Msg : String; Args : Array of const);
- begin
- FOwner.DoError(Msg,Args);
- end;
- { ---------------------------------------------------------------------
- TSimpleIPC
- ---------------------------------------------------------------------}
- procedure TSimpleIPC.DoError(Msg: String; Args: array of const);
- begin
- Raise EIPCError.Create(Name+': '+Format(Msg,Args));
- end;
- procedure TSimpleIPC.CheckInactive;
- begin
- If Active then
- DoError(SErrActive,[]);
- end;
- procedure TSimpleIPC.CheckActive;
- begin
- If Not Active then
- DoError(SErrInActive,[]);
- end;
- procedure TSimpleIPC.SetActive(const AValue: Boolean);
- begin
- if (FActive<>AValue) then
- begin
- If AValue then
- Activate
- else
- Deactivate;
- end;
- end;
- procedure TSimpleIPC.SetServerID(const AValue: String);
- begin
- if (FServerID<>AValue) then
- begin
- CheckInactive;
- FServerID:=AValue
- end;
- end;
- { ---------------------------------------------------------------------
- TSimpleIPCServer
- ---------------------------------------------------------------------}
- constructor TSimpleIPCServer.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FGlobal:=False;
- FActive:=False;
- FBusy:=False;
- FMsgData:=TStringStream.Create('');
- end;
- destructor TSimpleIPCServer.Destroy;
- begin
- Active:=False;
- FreeAndNil(FMsgData);
- inherited Destroy;
- end;
- procedure TSimpleIPCServer.SetGlobal(const AValue: Boolean);
- begin
- if (FGlobal<>AValue) then
- begin
- CheckInactive;
- FGlobal:=AValue;
- end;
- end;
- function TSimpleIPCServer.GetInstanceID: String;
- begin
- Result:=FIPCComm.InstanceID;
- end;
- function TSimpleIPCServer.GetStringMessage: String;
- begin
- Result:=TStringStream(FMsgData).DataString;
- end;
- procedure TSimpleIPCServer.StartServer;
- begin
- if Not Assigned(FIPCComm) then
- begin
- If (FServerID='') then
- FServerID:=ApplicationName;
- FIPCComm:=CommClass.Create(Self);
- FIPCComm.StartServer;
- end;
- FActive:=True;
- end;
- procedure TSimpleIPCServer.StopServer;
- begin
- If Assigned(FIPCComm) then
- begin
- FIPCComm.StopServer;
- FreeAndNil(FIPCComm);
- end;
- FActive:=False;
- end;
- function TSimpleIPCServer.PeekMessage(TimeOut: Integer; DoReadMessage: Boolean
- ): Boolean;
- begin
- CheckActive;
- FBusy:=True;
- Try
- Result:=FIPCComm.PeekMessage(Timeout);
- Finally
- FBusy:=False;
- end;
- If Result then
- If DoReadMessage then
- Readmessage;
- end;
- procedure TSimpleIPCServer.ReadMessage;
- begin
- CheckActive;
- FBusy:=True;
- Try
- FIPCComm.ReadMessage;
- If Assigned(FOnMessage) then
- FOnMessage(Self);
- Finally
- FBusy:=False;
- end;
- end;
- procedure TSimpleIPCServer.GetMessageData(Stream: TStream);
- begin
- Stream.CopyFrom(FMsgData,0);
- end;
- procedure TSimpleIPCServer.Activate;
- begin
- StartServer;
- end;
- procedure TSimpleIPCServer.Deactivate;
- begin
- StopServer;
- end;
- { ---------------------------------------------------------------------
- TSimpleIPCClient
- ---------------------------------------------------------------------}
- procedure TSimpleIPCClient.SetServerInstance(const AValue: String);
- begin
- CheckInactive;
- FServerInstance:=AVAlue;
- end;
- procedure TSimpleIPCClient.Activate;
- begin
- Connect;
- end;
- procedure TSimpleIPCClient.Deactivate;
- begin
- DisConnect;
- end;
- constructor TSimpleIPCClient.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- end;
- destructor TSimpleIPCClient.destroy;
- begin
- Active:=False;
- Inherited;
- end;
- procedure TSimpleIPCClient.Connect;
- begin
- If Not assigned(FIPCComm) then
- begin
- FIPCComm:=CommClass.Create(Self);
- Try
- FIPCComm.Connect;
- Except
- FreeAndNil(FIPCComm);
- Raise;
- end;
- FActive:=True;
- end;
- end;
- procedure TSimpleIPCClient.Disconnect;
- begin
- If Assigned(FIPCComm) then
- Try
- FIPCComm.DisConnect;
- Finally
- FActive:=False;
- FreeAndNil(FIPCComm);
- end;
- end;
- function TSimpleIPCClient.ServerRunning: Boolean;
- begin
- If Assigned(FIPCComm) then
- Result:=FIPCComm.ServerRunning
- else
- With CommClass.Create(Self) do
- Try
- Result:=ServerRunning;
- finally
- Free;
- end;
- end;
- procedure TSimpleIPCClient.SendMessage(MsgType : TMessageType; Stream: TStream);
- begin
- CheckActive;
- FBusy:=True;
- Try
- FIPCComm.SendMessage(MsgType,Stream);
- Finally
- FBusy:=False;
- end;
- end;
- procedure TSimpleIPCClient.SendStringMessage(const Msg: String);
- begin
- SendStringMessage(mtString,Msg);
- end;
- procedure TSimpleIPCClient.SendStringMessage(MsgType: TMessageType; const Msg: String
- );
- Var
- S : TStringStream;
- begin
- S:=TStringStream.Create(Msg);
- try
- SendMessage(MsgType,S);
- finally
- S.free;
- end;
- end;
- procedure TSimpleIPCClient.SendStringMessageFmt(const Msg: String;
- Args: array of const);
- begin
- SendStringMessageFmt(mtString,Msg,Args);
- end;
- procedure TSimpleIPCClient.SendStringMessageFmt(MsgType: TMessageType;
- const Msg: String; Args: array of const);
- begin
- SendStringMessage(MsgType, Format(Msg,Args));
- end;
- {$IFDEF OSNEEDIPCINITDONE}
- initialization
- IPCInit;
- finalization
- IPCDone;
- {$ENDIF}
- end.
|