simpleipc.pp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. {
  2. This file is part of the Free Component library.
  3. Copyright (c) 2005 by Michael Van Canneyt, member of
  4. the Free Pascal development team
  5. Unit implementing one-way IPC between 2 processes
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit simpleipc;
  13. {$mode objfpc}{$H+}
  14. interface
  15. uses
  16. Classes, SysUtils;
  17. Const
  18. MsgVersion = 1;
  19. Type
  20. TMessageType = (mtUnknown,mtString); // For now
  21. TMsgHeader = Packed record
  22. Version : Byte;
  23. msgType : TMessageType;
  24. MsgLen : Integer;
  25. end;
  26. TSimpleIPCServer = class;
  27. TSimpleIPCClient = class;
  28. { TIPCServerComm }
  29. TIPCServerComm = Class(TObject)
  30. Private
  31. FOwner : TSimpleIPCServer;
  32. Public
  33. Constructor Create(AOwner : TSimpleIPCServer); virtual;
  34. Property Owner : TSimpleIPCServer read FOwner;
  35. Procedure StartServer; virtual; Abstract;
  36. Procedure StopServer;virtual; Abstract;
  37. Function PeekMessage(TimeOut : Integer) : Boolean;virtual; Abstract;
  38. Function GetInstanceID : String; virtual; abstract;
  39. Procedure ReadMessage ;virtual; Abstract;
  40. Property InstanceID : String read GetInstanceID;
  41. end;
  42. TIPCServerCommClass = Class of TIPCServerComm;
  43. { TSimpleIPC }
  44. TSimpleIPC = Class(TComponent)
  45. Private
  46. procedure SetActive(const AValue: Boolean);
  47. procedure SetServerID(const AValue: String);
  48. Protected
  49. FBusy: Boolean;
  50. FActive : Boolean;
  51. FServerID : String;
  52. Procedure DoError(Msg : String; Args : Array of const);
  53. Procedure CheckInactive;
  54. Procedure CheckActive;
  55. Procedure Activate; virtual; abstract;
  56. Procedure Deactivate; virtual; abstract;
  57. Property Busy : Boolean Read FBusy;
  58. Published
  59. Property Active : Boolean Read FActive Write SetActive;
  60. Property ServerID : String Read FServerID Write SetServerID;
  61. end;
  62. { TSimpleIPCServer }
  63. TSimpleIPCServer = Class(TSimpleIPC)
  64. private
  65. FGlobal: Boolean;
  66. FOnMessage: TNotifyEvent;
  67. FMsgData : TStream;
  68. function GetInstanceID: String;
  69. function GetStringMessage: String;
  70. procedure SetGlobal(const AValue: Boolean);
  71. Protected
  72. FIPCComm: TIPCServerComm;
  73. Function CommClass : TIPCServerCommClass; virtual;
  74. Procedure Activate; override;
  75. Procedure Deactivate; override;
  76. Procedure ReadMessage;
  77. Public
  78. Constructor Create(AOwner : TComponent); override;
  79. Destructor destroy; override;
  80. Procedure StartServer;
  81. Procedure StopServer;
  82. Function PeekMessage(TimeOut : Integer; DoReadMessage : Boolean): Boolean;
  83. Property StringMessage : String Read GetStringMessage;
  84. Procedure GetMessageData(Stream : TStream);
  85. Property MsgData : TStream Read FMsgData;
  86. Property InstanceID : String Read GetInstanceID;
  87. Published
  88. Property Global : Boolean Read FGlobal Write SetGlobal;
  89. Property OnMessage : TNotifyEvent Read FOnMessage Write FOnMessage;
  90. end;
  91. { TIPCClientComm}
  92. TIPCClientComm = Class(TObject)
  93. private
  94. FOwner: TSimpleIPCClient;
  95. Public
  96. Constructor Create(AOwner : TSimpleIPCClient); virtual;
  97. Property Owner : TSimpleIPCClient read FOwner;
  98. Procedure Connect; virtual; abstract;
  99. Procedure Disconnect; virtual; abstract;
  100. Function ServerRunning : Boolean; virtual; abstract;
  101. Procedure SendMessage(MsgType : TMessageType; Stream : TStream);virtual;Abstract;
  102. end;
  103. TIPCClientCommClass = Class of TIPCClientComm;
  104. { TSimpleIPCClient }
  105. TSimpleIPCClient = Class(TSimpleIPC)
  106. Private
  107. FServerInstance: String;
  108. procedure SetServerInstance(const AValue: String);
  109. Protected
  110. FIPCComm : TIPCClientComm;
  111. Procedure Activate; override;
  112. Procedure Deactivate; override;
  113. Function CommClass : TIPCClientCommClass; virtual;
  114. Public
  115. Constructor Create(AOwner : TComponent); override;
  116. Destructor destroy; override;
  117. Procedure Connect;
  118. Procedure Disconnect;
  119. Function ServerRunning : Boolean;
  120. Procedure SendMessage(MsgType : TMessageType; Stream: TStream);
  121. Procedure SendStringMessage(Msg : String);
  122. Procedure SendStringmessageFmt(Msg : String; Args : Array of const);
  123. Property ServerInstance : String Read FServerInstance Write SetServerInstance;
  124. end;
  125. EIPCError = Class(Exception);
  126. Var
  127. DefaultIPCServerClass : TIPCServerCommClass = Nil;
  128. DefaultIPCClientClass : TIPCClientCommClass = Nil;
  129. resourcestring
  130. SErrServerNotActive = 'Server with ID %s is not active.';
  131. SErrActive = 'This operation is illegal when the server is active.';
  132. SErrInActive = 'This operation is illegal when the server is inactive.';
  133. implementation
  134. { ---------------------------------------------------------------------
  135. Include platform specific implementation.
  136. Should implement the CommClass method of both server and client component,
  137. as well as the communication class itself.
  138. This comes first, to allow the uses clause to be set.
  139. --------------------------------------------------------------------- }
  140. {$i simpleipc.inc}
  141. { ---------------------------------------------------------------------
  142. TIPCServerComm
  143. ---------------------------------------------------------------------}
  144. constructor TIPCServerComm.Create(AOwner: TSimpleIPCServer);
  145. begin
  146. FOwner:=AOWner;
  147. end;
  148. { ---------------------------------------------------------------------
  149. TIPCClientComm
  150. ---------------------------------------------------------------------}
  151. constructor TIPCClientComm.Create(AOwner: TSimpleIPCClient);
  152. begin
  153. FOwner:=AOwner;
  154. end;
  155. { ---------------------------------------------------------------------
  156. TSimpleIPC
  157. ---------------------------------------------------------------------}
  158. procedure TSimpleIPC.DoError(Msg: String; Args: array of const);
  159. begin
  160. Raise EIPCError.Create(Name+': '+Format(Msg,Args));
  161. end;
  162. procedure TSimpleIPC.CheckInactive;
  163. begin
  164. If Active then
  165. DoError(SErrActive,[]);
  166. end;
  167. procedure TSimpleIPC.CheckActive;
  168. begin
  169. If Not Active then
  170. DoError(SErrInActive,[]);
  171. end;
  172. procedure TSimpleIPC.SetActive(const AValue: Boolean);
  173. begin
  174. if (FActive<>AValue) then
  175. begin
  176. If AValue then
  177. Activate
  178. else
  179. Deactivate;
  180. end;
  181. end;
  182. procedure TSimpleIPC.SetServerID(const AValue: String);
  183. begin
  184. if (FServerID<>AValue) then
  185. begin
  186. CheckInactive;
  187. FServerID:=AValue
  188. end;
  189. end;
  190. { ---------------------------------------------------------------------
  191. TSimpleIPCServer
  192. ---------------------------------------------------------------------}
  193. constructor TSimpleIPCServer.Create(AOwner: TComponent);
  194. begin
  195. inherited Create(AOwner);
  196. FGlobal:=False;
  197. FActive:=False;
  198. FBusy:=False;
  199. FMsgData:=TStringStream.Create('');
  200. end;
  201. destructor TSimpleIPCServer.destroy;
  202. begin
  203. Active:=False;
  204. inherited destroy;
  205. end;
  206. procedure TSimpleIPCServer.SetGlobal(const AValue: Boolean);
  207. begin
  208. if (FGlobal<>AValue) then
  209. begin
  210. CheckInactive;
  211. FGlobal:=AValue;
  212. end;
  213. end;
  214. function TSimpleIPCServer.GetInstanceID: String;
  215. begin
  216. Result:=FIPCComm.InstanceID;
  217. end;
  218. function TSimpleIPCServer.GetStringMessage: String;
  219. begin
  220. Result:=TStringStream(FMsgData).DataString;
  221. end;
  222. procedure TSimpleIPCServer.StartServer;
  223. begin
  224. If (FServerID='') then
  225. FServerID:=ApplicationName;
  226. FIPCComm:=CommClass.Create(Self);
  227. FIPCComm.StartServer;
  228. FActive:=True;
  229. end;
  230. procedure TSimpleIPCServer.StopServer;
  231. begin
  232. FIPCComm.StopServer;
  233. FreeAndNil(FIPCComm);
  234. FActive:=False;
  235. end;
  236. function TSimpleIPCServer.PeekMessage(TimeOut: Integer; DoReadMessage: Boolean
  237. ): Boolean;
  238. begin
  239. CheckActive;
  240. FBusy:=True;
  241. Try
  242. Result:=FIPCComm.PeekMessage(Timeout);
  243. Finally
  244. FBusy:=False;
  245. end;
  246. If Result then
  247. If DoReadMessage then
  248. Readmessage;
  249. end;
  250. procedure TSimpleIPCServer.ReadMessage;
  251. begin
  252. CheckActive;
  253. FBusy:=True;
  254. Try
  255. FIPCComm.ReadMessage;
  256. If Assigned(FOnMessage) then
  257. FOnMessage(Self);
  258. Finally
  259. FBusy:=False;
  260. end;
  261. end;
  262. procedure TSimpleIPCServer.GetMessageData(Stream: TStream);
  263. begin
  264. Stream.CopyFrom(FMsgData,0);
  265. end;
  266. procedure TSimpleIPCServer.Activate;
  267. begin
  268. StartServer;
  269. end;
  270. procedure TSimpleIPCServer.Deactivate;
  271. begin
  272. StopServer;
  273. end;
  274. { ---------------------------------------------------------------------
  275. TSimpleIPCClient
  276. ---------------------------------------------------------------------}
  277. procedure TSimpleIPCClient.SetServerInstance(const AValue: String);
  278. begin
  279. CheckInactive;
  280. FServerInstance:=AVAlue;
  281. end;
  282. procedure TSimpleIPCClient.Activate;
  283. begin
  284. Connect;
  285. end;
  286. procedure TSimpleIPCClient.Deactivate;
  287. begin
  288. DisConnect;
  289. end;
  290. constructor TSimpleIPCClient.Create(AOwner: TComponent);
  291. begin
  292. inherited Create(AOwner);
  293. end;
  294. destructor TSimpleIPCClient.destroy;
  295. begin
  296. Active:=False;
  297. Inherited;
  298. end;
  299. procedure TSimpleIPCClient.Connect;
  300. begin
  301. FIPCComm:=CommClass.Create(Self);
  302. FIPCComm.Connect;
  303. FActive:=True;
  304. end;
  305. procedure TSimpleIPCClient.Disconnect;
  306. begin
  307. FIPCComm.DisConnect;
  308. FreeAndNil(FIPCComm);
  309. FActive:=False;
  310. end;
  311. function TSimpleIPCClient.ServerRunning: Boolean;
  312. begin
  313. If Assigned(FIPCComm) then
  314. Result:=FIPCComm.ServerRunning
  315. else
  316. With CommClass.Create(Self) do
  317. Try
  318. Result:=ServerRunning;
  319. finally
  320. Free;
  321. end;
  322. end;
  323. procedure TSimpleIPCClient.SendMessage(MsgType : TMessageType; Stream: TStream);
  324. begin
  325. CheckActive;
  326. FBusy:=True;
  327. Try
  328. FIPCComm.SendMessage(MsgType,Stream);
  329. Finally
  330. FBusy:=False;
  331. end;
  332. end;
  333. procedure TSimpleIPCClient.SendStringMessage(Msg: String);
  334. Var
  335. S : TStringStream;
  336. begin
  337. S:=TStringStream.Create(Msg);
  338. SendMessage(mtString,S);
  339. end;
  340. procedure TSimpleIPCClient.SendStringmessageFmt(Msg: String;
  341. Args: array of const);
  342. begin
  343. SendStringmessage(Format(Msg,Args));
  344. end;
  345. end.