/newStructBase/tangram framework/SysModuleMgr.pas

https://github.com/qriver/Delphi2010 · Pascal · 582 lines · 525 code · 41 blank · 16 comment · 18 complexity · d5d4729041eb678d25ed861412d333c0 MD5 · raw file

  1. { ------------------------------------
  2. ?????????
  3. ?????2010/05/11
  4. ???wzw
  5. ???wzw
  6. ------------------------------------- }
  7. unit SysModuleMgr;
  8. interface
  9. uses SysUtils, Classes, Windows, Contnrs, RegIntf, SplashFormIntf,
  10. ModuleInfoIntf, SvcInfoIntf, SysModule,ModuleLoaderIntf,StrUtils,
  11. uIntfObj,ModuleInstallerIntf,SysNotifyService,NotifyServiceIntf;
  12. Type
  13. TGetModuleClassPro = function :TModuleClass;
  14. TModuleType=(mtUnknow,mtBPL,mtDLL);
  15. TTangramModule = Class(TObject)
  16. private
  17. FLoadBatch:String;
  18. FModuleHandle: HMODULE;
  19. FModuleFileName: String;
  20. FModuleObj: TModule;
  21. FModuleCls:TModuleClass;
  22. FValidModule: Boolean;
  23. function GetModuleType: TModuleType;
  24. function LoadModule:THandle;
  25. procedure UnLoadModule;
  26. function GetModuleName: String;
  27. protected
  28. public
  29. Constructor Create(const mFile: String;
  30. LoadBatch:String='';CreateModuleObjInstance:Boolean=True);
  31. Destructor Destroy; override;
  32. property ModuleFileName: String Read FModuleFileName;
  33. property ModuleType:TModuleType Read GetModuleType;
  34. property ModuleName:String Read GetModuleName;
  35. procedure ModuleNotify(Flags: Integer; Intf: IInterface);
  36. procedure ModuleInit(const LoadBatch:String);
  37. procedure ModuleFinal;
  38. procedure Install;
  39. procedure UnInstall;
  40. property IsValidModule:Boolean Read FValidModule;
  41. End;
  42. TModuleMgr = Class(TIntfObj, IModuleInfo,
  43. IModuleLoader,IModuleInstaller, ISvcInfoEx)
  44. private
  45. SplashForm: ISplashForm;
  46. Tick: Cardinal;
  47. FModuleList: TObjectList;
  48. FLoadBatch:String;
  49. FNotifyService:TNotifyService;
  50. procedure WriteErrFmt(const err: String; const Args: array of const );
  51. function FormatPath(const s: string): string;
  52. procedure GetModuleList(RegIntf: IRegistry; ModuleList: TStrings;
  53. const Key: String);
  54. function FindModule(const ModuleFile:string):TTangramModule;
  55. protected
  56. {IModuleLoader}
  57. procedure LoadBegin;
  58. procedure LoadModuleFromFile(const ModuleFile: string);
  59. procedure LoadModulesFromDir(const Dir:String='');
  60. procedure LoadFinish;
  61. procedure UnLoadModule(const ModuleFile:string);
  62. function ModuleLoaded(const ModuleFile:string):Boolean;
  63. { IModuleInfo }
  64. procedure GetModuleInfo(ModuleInfoGetter: IModuleInfoGetter);
  65. { ISvcInfoEx }
  66. procedure GetSvcInfo(Intf:ISvcInfoGetter);
  67. {IModuleInstaller}
  68. procedure InstallModule(const ModuleFile:String);
  69. procedure UninstallModule(const ModuleFile:string);
  70. public
  71. Constructor Create;
  72. Destructor Destroy; override;
  73. procedure LoadModules;
  74. procedure Init;
  75. procedure final;
  76. end;
  77. implementation
  78. uses SysSvc, LogIntf, LoginIntf, StdVcl, AxCtrls, SysFactoryMgr,
  79. SysFactory,SysFactoryEx,IniFiles,RegObj,uSvcInfoObj,SysMsg;
  80. {$WARN SYMBOL_DEPRECATED OFF}
  81. {$WARN SYMBOL_PLATFORM OFF}
  82. const
  83. Value_Module='Module';
  84. Value_Load='LOAD';
  85. SplashFormWaitTime=1500;
  86. key_LoadModule='SYSTEM\LOADMODULE';
  87. procedure CreateRegObj(out anInstance: IInterface);
  88. var RegFile,IniFile,AppPath:String;
  89. Ini:TIniFile;
  90. begin
  91. AppPath:=ExtractFilePath(ParamStr(0));
  92. IniFile:=AppPath+'Root.ini';
  93. ini:=TIniFile.Create(IniFile);
  94. try
  95. RegFile:=AppPath+ini.ReadString('Default','Reg','Tangram.xml');
  96. anInstance:=TRegObj.Create;
  97. (anInstance as ILoadRegistryFile).LoadRegistryFile(RegFile);
  98. finally
  99. ini.Free;
  100. end;
  101. end;
  102. procedure Create_SvcInfoObj(out anInstance: IInterface);
  103. begin
  104. anInstance:=TSvcInfoObj.Create;
  105. end;
  106. { TTangramModule }
  107. constructor TTangramModule.Create(const mFile: String;LoadBatch:String='';
  108. CreateModuleObjInstance:Boolean=True);
  109. var
  110. GetModuleClassPro: TGetModuleClassPro;
  111. begin
  112. FValidModule:=False;
  113. FModuleObj := nil;
  114. FModuleCls :=nil;
  115. FLoadBatch:=LoadBatch;
  116. FModuleFileName := mFile;
  117. FModuleHandle := self.LoadModule;
  118. @GetModuleClassPro := GetProcAddress(FModuleHandle, 'GetModuleClass');
  119. if Assigned(GetModuleClassPro) then
  120. begin
  121. FModuleCls:=GetModuleClassPro;
  122. FValidModule:=FModuleCls<>nil;
  123. if (FModuleCls<>nil) and (CreateModuleObjInstance) then
  124. FModuleObj:=FModuleCls.Create;
  125. end;
  126. end;
  127. destructor TTangramModule.Destroy;
  128. begin
  129. if Assigned(FModuleObj) then
  130. FModuleObj.Free;
  131. self.UnLoadModule;
  132. inherited;
  133. end;
  134. function TTangramModule.GetModuleName: String;
  135. begin
  136. Result:=ExtractFileName(FModuleFileName);
  137. end;
  138. function TTangramModule.GetModuleType: TModuleType;
  139. var ext:String;
  140. begin
  141. ext:=ExtractFileExt(self.FModuleFileName);
  142. if SameText(ext,'.bpl') then
  143. Result:=mtBPL
  144. else Result:=mtDLL;
  145. end;
  146. function TTangramModule.LoadModule: THandle;
  147. begin
  148. Result:=0;
  149. case GetModuleType of
  150. mtBPL:Result:=SysUtils.LoadPackage(self.FModuleFileName);
  151. mtDLL:Result:=Windows.LoadLibrary(Pchar(self.FModuleFileName));
  152. end;
  153. end;
  154. procedure TTangramModule.ModuleFinal;
  155. begin
  156. if FModuleObj<>nil then
  157. FModuleObj.final;
  158. end;
  159. procedure TTangramModule.ModuleInit(const LoadBatch: String);
  160. begin
  161. if FModuleObj<>nil then
  162. begin
  163. if self.FLoadBatch=LoadBatch then
  164. FModuleObj.Init;
  165. end;
  166. end;
  167. procedure TTangramModule.Install;
  168. var Reg:IRegistry;
  169. begin
  170. if FModuleCls<>nil then
  171. begin
  172. Reg:=SysService as IRegistry;
  173. FModuleCls.RegisterModule(Reg);
  174. end;
  175. end;
  176. procedure TTangramModule.ModuleNotify(Flags: Integer; Intf: IInterface);
  177. begin
  178. if FModuleObj<>nil then
  179. FModuleObj.Notify(Flags,Intf);
  180. end;
  181. procedure TTangramModule.UnInstall;
  182. var Reg:IRegistry;
  183. begin
  184. if FModuleCls<>nil then
  185. begin
  186. Reg:=SysService as IRegistry;
  187. FModuleCls.UnRegisterModule(Reg);
  188. end;
  189. end;
  190. procedure TTangramModule.UnLoadModule;
  191. begin
  192. case GetModuleType of
  193. mtBPL:SysUtils.UnloadPackage(self.FModuleHandle);
  194. mtDLL:Windows.FreeLibrary(self.FModuleHandle);
  195. end;
  196. end;
  197. { TModuleMgr }
  198. procedure TModuleMgr.GetSvcInfo(Intf: ISvcInfoGetter);
  199. var SvrInfo:TSvcInfoRec;
  200. begin
  201. SvrInfo.ModuleName:=ExtractFileName(SysUtils.GetModuleName(HInstance));
  202. SvrInfo.GUID:=GUIDToString(IModuleInfo);
  203. SvrInfo.Title:='??????(IModuleInfo)';
  204. SvrInfo.Version:='20100512.001';
  205. SvrInfo.Comments:= '????????????????????';
  206. Intf.SvcInfo(SvrInfo);
  207. SvrInfo.GUID:=GUIDToString(IModuleLoader);
  208. SvrInfo.Title:='??????(IModuleLoader)';
  209. SvrInfo.Version:='20110225.001';
  210. SvrInfo.Comments:= '??????????????????????????????';
  211. Intf.SvcInfo(SvrInfo);
  212. SvrInfo.GUID:=GUIDToString(IModuleInstaller);
  213. SvrInfo.Title:='??????(IModuleInstaller)';
  214. SvrInfo.Version:='20110420.001';
  215. SvrInfo.Comments:= '?????????';
  216. Intf.SvcInfo(SvrInfo);
  217. end;
  218. constructor TModuleMgr.Create;
  219. begin
  220. FLoadBatch:='';
  221. FModuleList := TObjectList.Create(True);
  222. FNotifyService:=TNotifyService.Create;
  223. TSingletonFactory.Create(IRegistry,@CreateRegObj);
  224. TObjFactoryEx.Create([IModuleInfo,IModuleLoader,IModuleInstaller], self);
  225. TIntfFactory.Create(ISvcInfoEx,@Create_SvcInfoObj);
  226. end;
  227. destructor TModuleMgr.Destroy;
  228. begin
  229. FNotifyService.Free;
  230. FModuleList.Free;
  231. inherited;
  232. end;
  233. function TModuleMgr.FindModule(const ModuleFile: string): TTangramModule;
  234. var
  235. i: Integer;
  236. Module: TTangramModule;
  237. begin
  238. Result:=nil;
  239. for i := 0 to FModuleList.Count - 1 do
  240. begin
  241. Module := TTangramModule(FModuleList[i]);
  242. if SameText(Module.ModuleFileName,ModuleFile) then
  243. begin
  244. Result:=Module;
  245. Break;
  246. end;
  247. end;
  248. end;
  249. function TModuleMgr.FormatPath(const s: string): string;
  250. const
  251. Var_AppPath = '($APP_PATH)';
  252. begin
  253. Result := StringReplace(s, Var_AppPath, ExtractFilePath(Paramstr(0)),
  254. [rfReplaceAll, rfIgnoreCase]);
  255. end;
  256. procedure TModuleMgr.GetModuleList(RegIntf: IRegistry; ModuleList: TStrings;
  257. const Key: String);
  258. var
  259. SubKeyList, ValueList, aList: TStrings;
  260. i: Integer;
  261. valueStr: string;
  262. valueName, vStr, ModuleFile, Load: WideString;
  263. begin
  264. SubKeyList := TStringList.Create;
  265. ValueList := TStringList.Create;
  266. aList := TStringList.Create;
  267. try
  268. RegIntf.OpenKey(Key, False);
  269. // ???
  270. RegIntf.GetValueNames(ValueList);
  271. for i := 0 to ValueList.Count - 1 do
  272. begin
  273. aList.Clear;
  274. valueName := ValueList[i];
  275. if RegIntf.ReadString(valueName, vStr) then
  276. begin
  277. valueStr := AnsiUpperCase(vStr);
  278. ExtractStrings([';'], [], pchar(valueStr), aList);
  279. ModuleFile := FormatPath(aList.Values[Value_Module]);
  280. Load := aList.Values[Value_Load];
  281. if (ModuleFile <> '') and (CompareText(Load, 'TRUE') = 0) then
  282. ModuleList.Add(ModuleFile);
  283. end;
  284. end;
  285. // ????
  286. RegIntf.GetKeyNames(SubKeyList);
  287. for i := 0 to SubKeyList.Count - 1 do
  288. GetModuleList(RegIntf, ModuleList, Key + '\' + SubKeyList[i]); // ??
  289. finally
  290. SubKeyList.Free;
  291. ValueList.Free;
  292. aList.Free;
  293. end;
  294. end;
  295. function TModuleMgr.ModuleLoaded(const ModuleFile: string): Boolean;
  296. begin
  297. Result:=FindModule(ModuleFile)<>nil;
  298. end;
  299. procedure TModuleMgr.GetModuleInfo(ModuleInfoGetter: IModuleInfoGetter);
  300. var
  301. i: Integer;
  302. Module: TTangramModule;
  303. MInfo: TModuleInfo;
  304. begin
  305. if ModuleInfoGetter = nil then
  306. exit;
  307. for i := 0 to FModuleList.Count - 1 do
  308. begin
  309. Module := TTangramModule(FModuleList[i]);
  310. MInfo.PackageName := Module.ModuleFileName;
  311. MInfo.Description := GetPackageDescription(pchar(MInfo.PackageName));
  312. ModuleInfoGetter.ModuleInfo(MInfo);
  313. end;
  314. end;
  315. procedure TModuleMgr.Init;
  316. var
  317. CurTick, UseTime,WaitTime: Cardinal;
  318. LoginIntf: ILogin;
  319. Module: TTangramModule;
  320. i:Integer;
  321. begin
  322. Module := nil;
  323. for i := 0 to FModuleList.Count - 1 do
  324. begin
  325. Try
  326. Module := TTangramModule(FModuleList.Items[i]);
  327. if Assigned(SplashForm) then
  328. SplashForm.loading(Format(Msg_InitingModule,[Module.ModuleName]));
  329. Module.ModuleInit(self.FLoadBatch);
  330. Except
  331. on E: Exception do
  332. begin
  333. WriteErrFmt(Err_InitModule,[Module.ModuleName,E.Message]);
  334. end;
  335. End;
  336. end;
  337. // ??Splash??
  338. if Assigned(SplashForm) then
  339. begin
  340. CurTick := GetTickCount;
  341. UseTime := CurTick - Tick;
  342. WaitTime:=SplashForm.GetWaitTime;
  343. if WaitTime=0 then
  344. WaitTime:=SplashFormWaitTime;
  345. if UseTime < WaitTime then
  346. begin
  347. SplashForm.loading(Msg_WaitingLogin);
  348. sleep(WaitTime - UseTime);
  349. end;
  350. SplashForm.Hide;
  351. //FactoryManager.FindFactory(ISplashForm).Free;
  352. SplashForm := nil;
  353. end;
  354. // ????
  355. if SysService.QueryInterface(ILogin, LoginIntf) = S_OK then
  356. LoginIntf.CheckLogin;
  357. end;
  358. procedure TModuleMgr.LoadModules;
  359. var
  360. aList: TStrings;
  361. i: Integer;
  362. RegIntf: IRegistry;
  363. ModuleFile: String;
  364. begin
  365. aList := TStringList.Create;
  366. try
  367. SplashForm := nil;
  368. RegIntf := SysService as IRegistry;
  369. GetModuleList(RegIntf, aList, key_LoadModule);
  370. for i := 0 to aList.Count - 1 do
  371. begin
  372. ModuleFile := aList[i];
  373. if Assigned(SplashForm) then
  374. SplashForm.loading(Format(Msg_LoadingModule,
  375. [ExtractFileName(ModuleFile)]));
  376. // ???
  377. if FileExists(ModuleFile) then
  378. LoadModuleFromFile(ModuleFile)
  379. else
  380. WriteErrFmt(Err_ModuleNotExists, [ModuleFile]);
  381. // ??Falsh??
  382. if SplashForm = nil then
  383. begin
  384. if SysService.QueryInterface(ISplashForm, SplashForm) = S_OK then
  385. begin
  386. Tick := GetTickCount;
  387. SplashForm.Show;
  388. end;
  389. end;
  390. end;
  391. finally
  392. aList.Free;
  393. end;
  394. end;
  395. procedure TModuleMgr.LoadBegin;
  396. var BatchID:TGUID;
  397. begin
  398. if CreateGUID(BatchID)=S_OK then
  399. self.FLoadBatch:=GUIDToString(BatchID);
  400. end;
  401. procedure TModuleMgr.LoadFinish;
  402. begin
  403. self.Init;
  404. end;
  405. procedure TModuleMgr.LoadModulesFromDir(const Dir: String);
  406. var DR: TSearchRec;
  407. ZR: Integer;
  408. TmpPath,FileExt,FullFileName:String;
  409. begin
  410. if Dir='' then
  411. TmpPath:=ExtractFilePath(ParamStr(0))
  412. else begin
  413. if RightStr(Dir,1)='\' then
  414. TmpPath:=Dir
  415. else tmpPath:=Dir+'\';
  416. end;
  417. ZR:=SysUtils.FindFirst(TmpPath+ '*.*', FaAnyfile, DR);
  418. try
  419. while ZR = 0 do
  420. begin
  421. if ((DR.Attr and FaDirectory <> FaDirectory)
  422. and (DR.Attr and FaVolumeID <> FaVolumeID))
  423. and (DR.Name <> '.') and (DR.Name <> '..') then
  424. begin
  425. FullFileName:=tmpPath+DR.Name;
  426. FileExt:=ExtractFileExt(FullFileName);
  427. if SameText(FileExt,'.dll') or
  428. SameText(FileExt,'.bpl') then
  429. self.LoadModuleFromFile(FullFileName);
  430. end;
  431. ZR := SysUtils.FindNext(DR);
  432. end;//end while
  433. finally
  434. SysUtils.FindClose(DR);
  435. end;
  436. end;
  437. procedure TModuleMgr.LoadModuleFromFile(const ModuleFile: string);
  438. var Module:TTangramModule;
  439. begin
  440. try
  441. Module:=TTangramModule.Create(ModuleFile,self.FLoadBatch);
  442. if Module.IsValidModule then
  443. FModuleList.Add(Module)
  444. else Module.Free;
  445. Except
  446. on E: Exception do
  447. begin
  448. WriteErrFmt(Err_LoadModule, [ExtractFileName(ModuleFile), E.Message]);
  449. end;
  450. end;
  451. end;
  452. procedure TModuleMgr.UnLoadModule(const moduleFile: string);
  453. var Module:TTangramModule;
  454. begin
  455. Module:=self.FindModule(ModuleFile);
  456. if Module<>nil then
  457. FModuleList.Remove(Module);
  458. end;
  459. procedure TModuleMgr.final;
  460. var
  461. i: Integer;
  462. Module: TTangramModule;
  463. begin
  464. for i := 0 to FModuleList.Count - 1 do
  465. begin
  466. Module := TTangramModule(FModuleList.Items[i]);
  467. try
  468. Module.ModuleFinal;
  469. Except
  470. on E:Exception do
  471. self.WriteErrFmt(Err_finalModule,[Module.ModuleName,E.Message]);
  472. end;
  473. end;
  474. FactoryManager.ReleaseInstances;
  475. end;
  476. procedure TModuleMgr.WriteErrFmt(const err: String;
  477. const Args: array of const );
  478. var
  479. Log: ILog;
  480. begin
  481. if SysService.QueryInterface(ILog, Log) = S_OK then
  482. Log.WriteLogFmt(err, Args);
  483. end;
  484. procedure TModuleMgr.InstallModule(const ModuleFile: String);
  485. var Module:TTangramModule;
  486. begin
  487. Module:=self.FindModule(ModuleFile);
  488. if Module=nil then
  489. begin
  490. Module:=TTangramModule.Create(ModuleFile,'',False);
  491. if Module.IsValidModule then
  492. FModuleList.Add(Module)
  493. else begin
  494. Module.Free;
  495. exit;
  496. end;
  497. end;
  498. Module.Install;
  499. end;
  500. procedure TModuleMgr.UninstallModule(const ModuleFile: string);
  501. var Module:TTangramModule;
  502. begin
  503. Module:=self.FindModule(ModuleFile);
  504. if Module=nil then
  505. begin
  506. Module:=TTangramModule.Create(ModuleFile,'',False);
  507. if Module.IsValidModule then
  508. FModuleList.Add(Module)
  509. else begin
  510. Module.Free;
  511. exit;
  512. end;
  513. end;
  514. Module.UnInstall;
  515. end;
  516. initialization
  517. finalization
  518. end.