Quick.Config.Registry.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. { ***************************************************************************
  2. Copyright (c) 2015-2019 Kike Pérez
  3. Unit : Quick.Config.Registry
  4. Description : Save config to Windows Registry
  5. Author : Kike Pérez
  6. Version : 1.5
  7. Created : 21/10/2017
  8. Modified : 25/01/2019
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Config.Registry;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. Windows,
  27. SysUtils,
  28. Registry,
  29. Quick.Json.Serializer,
  30. {$IFDEF DELPHIRX102_UP}
  31. System.Json,
  32. System.JSON.Types,
  33. {$ELSE}
  34. {$IFDEF FPC}
  35. fpjson,
  36. //jsonparser,
  37. //fpjsonrtti,
  38. Quick.Json.fpc.Compatibility,
  39. {$ELSE}
  40. Rest.Json.Types,
  41. System.JSON,
  42. Rest.Json,
  43. {$ENDIF}
  44. {$ENDIF}
  45. Quick.Commons,
  46. Quick.Config.Base;
  47. type
  48. TAppConfigRegistryProvider = class(TAppConfigProvider)
  49. private
  50. fRootKey : HKEY;
  51. fMainKey : string;
  52. fRegConfig : TRegistry;
  53. function JsonToRegistry(const StrJson : string) : Boolean;
  54. function RegistryToJson(out StrJson : string) : Boolean;
  55. class function IsSimpleJsonValue(v: TJSONValue): Boolean;
  56. function IsRegKeyObject(const cCurrentKey : string = '') : Boolean;
  57. function IsRegKeyArray(const cCurrentKey : string = '') : Boolean;
  58. function ProcessPairRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
  59. function ProcessElementRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
  60. procedure ProcessPairWrite(const cCurrentKey: string; obj: TJSONObject; aIndex: integer);
  61. procedure ProcessElementWrite(const cCurrentKey: string; arr: TJSONArray; aIndex, aMax : integer);
  62. function AddRegKey(const cCurrentKey, NewKey : string) : Boolean;
  63. function ReadRegValue(const cCurrentKey, cName : string) : TJSONValue;
  64. procedure AddRegValue(const cCurrentKey, cName : string; cValue : TJSONValue);
  65. protected
  66. procedure Load(cConfig : TAppConfig); override;
  67. procedure Save(cConfig : TAppConfig); override;
  68. public
  69. constructor Create(aHRoot : HKEY = HKEY_CURRENT_USER; const aMainKey : string = ''); virtual;
  70. destructor Destroy; override;
  71. property HRoot : HKEY read fRootKey write fRootKey;
  72. property MainKey : string read fMainKey write fMainKey;
  73. end;
  74. EAppConfig = Exception;
  75. TAppConfigRegistry = class(TAppConfig)
  76. private
  77. function GetProvider : TAppConfigRegistryProvider;
  78. public
  79. constructor Create(aHRoot : HKEY = HKEY_CURRENT_USER; const aMainKey : string = '');
  80. destructor Destroy; override;
  81. property Provider : TAppConfigRegistryProvider read GetProvider;
  82. end;
  83. {Usage: create a descend class from TAppConfigRegistry and add published properties to be loaded/saved
  84. TMyConfig = class(TAppConfigRegistry)
  85. private
  86. fName : string;
  87. fSurname : string;
  88. fStatus : Integer;
  89. published
  90. property Name : string read fName write fName;
  91. property SurName : string read fSurname write fSurname;
  92. property Status : Integer read fStatus write fStatus;
  93. end;
  94. MyConfig := TMyConfig.Create;
  95. MyConfig.Provider.MainKey := 'MyAppName';
  96. MyConfig.Name := 'John';
  97. MyConfig.Save;
  98. }
  99. implementation
  100. { TAppConfigRegistryProvider }
  101. constructor TAppConfigRegistryProvider.Create(aHRoot : HKEY = HKEY_CURRENT_USER; const aMainKey : string = '');
  102. begin
  103. inherited Create;
  104. if aHRoot <> HKEY_CURRENT_USER then fRootKey := aHRoot
  105. else fRootKey := HKEY_CURRENT_USER;
  106. if aMainKey <> '' then fMainKey := aMainKey
  107. else fMainKey := ExtractFileNameWithoutExt(ParamStr(0));
  108. fRegConfig := TRegistry.Create(KEY_READ or KEY_WRITE);
  109. end;
  110. destructor TAppConfigRegistryProvider.Destroy;
  111. begin
  112. if Assigned(fRegConfig) then fRegConfig.Free;
  113. inherited;
  114. end;
  115. procedure TAppConfigRegistryProvider.Load(cConfig : TAppConfig);
  116. var
  117. Serializer: TJsonSerializer;
  118. json : string;
  119. begin
  120. fRegConfig.Access := KEY_READ;
  121. fRegConfig.RootKey := fRootKey;
  122. if not fRegConfig.KeyExists('\Software\' + fMainKey) then
  123. begin
  124. if not CreateIfNotExists then raise EAppConfig.Create('Not exists MainKey in registry!')
  125. else TAppConfigRegistry(cConfig).DefaultValues;
  126. Save(cConfig);
  127. end;
  128. RegistryToJson(json);
  129. serializer := TJsonSerializer.Create(slPublishedProperty);
  130. try
  131. serializer.JsonToObject(cConfig,json);
  132. finally
  133. serializer.Free;
  134. end;
  135. end;
  136. procedure TAppConfigRegistryProvider.Save(cConfig : TAppConfig);
  137. begin
  138. JsonToRegistry(cConfig.ToJSON);
  139. end;
  140. function TAppConfigRegistryProvider.JsonToRegistry(const StrJson : string) : Boolean;
  141. var
  142. jValue : TJSONValue;
  143. aCount : Integer;
  144. i : Integer;
  145. aCurrentKey : string;
  146. begin
  147. Result := False;
  148. if fMainKey = '' then raise EAppConfig.Create('MainKey not defined!');
  149. fRegConfig.Access := KEY_READ or KEY_WRITE;
  150. fRegConfig.RootKey := fRootKey;
  151. aCurrentKey := '\Software\' + fMainKey;
  152. if fRegConfig.KeyExists(aCurrentKey) then
  153. begin
  154. try
  155. if fRegConfig.KeyExists(aCurrentKey + '_bak') then fRegConfig.DeleteKey(aCurrentKey + '_bak');
  156. fRegConfig.MoveKey(aCurrentKey,aCurrentKey + '_bak',True);
  157. except
  158. raise EAppConfig.Create('Can''t write Config Registry');
  159. end;
  160. end;
  161. try
  162. if not AddRegKey('\Software',fMainKey) then
  163. begin
  164. raise EAppConfig.Create('Can''t create key');
  165. end;
  166. {$IFNDEF FPC}
  167. jValue := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONValue;
  168. {$ELSE}
  169. jValue := TJSONObject.ParseJSONValue(StrJson) as TJSONValue;
  170. {$ENDIF}
  171. try
  172. if IsSimpleJsonValue(jValue) then
  173. begin
  174. {$IFNDEF FPC}
  175. AddRegValue(aCurrentKey,TJSONPair(jValue).JsonString.ToString.DeQuotedString('"'),TJSONPair(jValue).JsonValue);
  176. {$ELSE}
  177. AddRegValue(aCurrentKey,TJSONPair(jValue).JsonString.DeQuotedString('"'),TJSONPair(jValue).JsonValue);
  178. {$ENDIF}
  179. end
  180. {$IFNDEF FPC}
  181. else if jValue is TJSONObject then
  182. {$ELSE}
  183. else if jvalue.JSONType = jtObject then
  184. {$ENDIF}
  185. begin
  186. aCount := TJSONObject(jValue).Count;
  187. for i := 0 to aCount - 1 do
  188. ProcessPairWrite(aCurrentKey,TJSONObject(jValue),i);
  189. end
  190. {$IFNDEF FPC}
  191. else if jValue is TJSONArray then
  192. {$ELSE}
  193. else if jValue.JSONType = jtArray then
  194. {$ENDIF}
  195. begin
  196. aCount := TJSONArray(jValue).Count;
  197. for i := 0 to aCount - 1 do
  198. ProcessElementWrite(aCurrentKey,TJSONArray(jValue),i,aCount);
  199. end
  200. else raise EAppConfig.Create('Error Saving config to Registry');
  201. Result := True;
  202. finally
  203. jValue.Free;
  204. end;
  205. if fRegConfig.KeyExists(aCurrentKey + '_bak') then fRegConfig.DeleteKey(aCurrentKey + '_bak');
  206. except
  207. on E : Exception do
  208. begin
  209. fRegConfig.DeleteKey(aCurrentKey);
  210. fRegConfig.MoveKey(aCurrentKey+'_bak',aCurrentKey,True);
  211. raise EAppConfig.Create(e.message);
  212. end;
  213. end;
  214. end;
  215. function TAppConfigRegistryProvider.RegistryToJson(out StrJson : string) : Boolean;
  216. var
  217. jValue : TJSONValue;
  218. jPair : TJSONPair;
  219. jArray : TJSONArray;
  220. a, b : string;
  221. aCount : Integer;
  222. i : Integer;
  223. aName : string;
  224. aValue : TJSONValue;
  225. aCurrentKey : string;
  226. newObj : TJSONObject;
  227. RegKeyList : TStringList;
  228. RegValueList : TStringList;
  229. RegKey : string;
  230. RegValue : string;
  231. RegKeyInfo : TRegKeyInfo;
  232. begin
  233. Result := False;
  234. //check if exists root key
  235. fRegConfig.Access := KEY_READ;
  236. fRegConfig.RootKey := fRootKey;
  237. if fRegConfig.KeyExists('\Software\' + fMainKey) then
  238. begin
  239. fRegConfig.OpenKeyReadOnly('\Software\' + fMainKey);
  240. aCurrentKey := '\Software\' + fMainKey;
  241. end
  242. else raise EAppConfig.Create('Can''t read key');
  243. newObj := TJSONObject.Create;
  244. try
  245. //read root values
  246. RegValueList := TStringList.Create;
  247. try
  248. fRegConfig.GetValueNames(RegValueList);
  249. for RegValue in RegValueList do
  250. begin
  251. newObj.AddPair(RegValue,ReadRegValue(aCurrentKey,RegValue));
  252. end;
  253. finally
  254. RegValueList.Free;
  255. end;
  256. //read root keys
  257. RegKeyList := TStringList.Create;
  258. try
  259. fRegConfig.GetKeyNames(RegKeyList);
  260. for RegKey in RegKeyList do
  261. begin
  262. fRegConfig.OpenKeyReadOnly(aCurrentKey + '\' + RegKey);
  263. if IsRegKeyObject then
  264. begin
  265. jValue := ProcessPairRead(aCurrentKey + '\' + RegKey,Regkey,i);
  266. newObj.AddPair(RegKey,jValue);
  267. end
  268. else if IsRegKeyArray then
  269. begin
  270. jValue := ProcessElementRead(aCurrentKey + '\' + RegKey,Regkey,i);
  271. newObj.AddPair(RegKey,jValue);
  272. end
  273. else raise EAppConfig.Create('Unknow value reading Config Registry');
  274. end;
  275. finally
  276. RegKeyList.Free;
  277. end;
  278. StrJson := newObj.ToJSON;
  279. finally
  280. newObj.Free;
  281. end;
  282. end;
  283. function TAppConfigRegistryProvider.IsRegKeyObject(const cCurrentKey : string = '') : Boolean;
  284. begin
  285. Result := not IsRegKeyArray(cCurrentKey);
  286. end;
  287. function TAppConfigRegistryProvider.IsRegKeyArray(const cCurrentKey : string = '') : Boolean;
  288. var
  289. RegValue : string;
  290. RegValueList : TStrings;
  291. RegKey : string;
  292. RegKeyList : TStrings;
  293. n : Integer;
  294. begin
  295. Result := False;
  296. if cCurrentKey <> '' then fRegConfig.OpenKeyReadOnly(cCurrentKey);
  297. // else Exit;
  298. //check if exists RegKey numeric (indicates is a Array)
  299. RegKeyList := TStringList.Create;
  300. try
  301. fRegConfig.GetKeyNames(RegKeyList);
  302. for RegKey in RegKeyList do
  303. if TryStrToInt(RegKey,n) then
  304. begin
  305. Result := True;
  306. Break;
  307. end;
  308. finally
  309. RegKeyList.Free;
  310. end;
  311. //check if exists RegValue numeric (indicates is a Array)
  312. RegValueList := TStringList.Create;
  313. try
  314. fRegConfig.GetValueNames(RegValueList);
  315. for RegValue in RegValueList do
  316. if TryStrToInt(RegValue,n) then
  317. begin
  318. Result := True;
  319. Break;
  320. end;
  321. finally
  322. RegValueList.Free;
  323. end;
  324. end;
  325. class function TAppConfigRegistryProvider.IsSimpleJsonValue(v: TJSONValue): Boolean;
  326. begin
  327. Result := (v is {$IFDEF FPC}fpjson.TJsonIntegerNumber{$ELSE}TJSONNumber{$ENDIF})
  328. or (v is {$IFDEF FPC}fpjson.{$ENDIF}TJSONString)
  329. {$IFNDEF FPC}
  330. or (v is TJSONTrue)
  331. or (v is TJSONFalse)
  332. {$ELSE}
  333. or (v is {$IFDEF FPC}fpjson.TJSONBoolean{$ELSE}TJsonBool{$ENDIF})
  334. {$ENDIF}
  335. or (v is {$IFDEF FPC}fpjson.{$ENDIF}TJSONNull);
  336. end;
  337. function TAppConfigRegistryProvider.ReadRegValue(const cCurrentKey, cName : string) : TJSONValue;
  338. var
  339. aValue : string;
  340. RegInfo : TRegDataInfo;
  341. begin
  342. if fRegConfig.OpenKeyReadOnly(cCurrentKey) then
  343. begin
  344. if fRegConfig.GetDataInfo(cName,RegInfo) then
  345. case RegInfo.RegData of
  346. rdInteger : Result := TJSONNumber.Create(fRegConfig.ReadInteger(cName));
  347. rdString :
  348. begin
  349. aValue := fRegConfig.ReadString(cName);
  350. if aValue.ToLower = 'true' then Result := TJSONBool.Create(True)
  351. else if aValue.ToLower = 'false' then Result := TJSONBool.Create(False)
  352. else Result := TJSONString.Create(aValue);
  353. end;
  354. else Result := TJSONNull.Create;
  355. end;
  356. end;
  357. end;
  358. function TAppConfigRegistryProvider.AddRegKey(const cCurrentKey, NewKey : string) : Boolean;
  359. begin
  360. Result := fRegConfig.CreateKey(Format('%s\%s',[cCurrentKey,NewKey]));
  361. end;
  362. procedure TAppConfigRegistryProvider.AddRegValue(const cCurrentKey, cName : string; cValue : TJSONValue);
  363. var
  364. aName : string;
  365. aValue : string;
  366. begin
  367. aName := cName.DeQuotedString('"');
  368. {$IFNDEF FPC}
  369. aValue := cValue.ToString.DeQuotedString('"');
  370. {$ELSE}
  371. aValue := cValue.AsString;// .DeQuotedString('"');
  372. {$ENDIF}
  373. fRegConfig.OpenKey(cCurrentKey,True);
  374. if cValue is {$IFDEF FPC}fpjson.TJSONIntegerNumber{$ELSE}TJSONNumber{$ENDIF} then fRegConfig.WriteInteger(aName,StrToInt64(aValue))
  375. else if cValue is {$IFDEF FPC}fpjson.{$ENDIF}TJSONString then fRegConfig.WriteString(aName,aValue)
  376. else if cValue is {$IFDEF FPC}fpjson.TJSONBoolean{$ELSE}TJSONBool{$ENDIF} then fRegConfig.WriteString(aName,aValue);
  377. //else if cValue is TJSONNull then fRegConfig.WriteString(aName,'');
  378. end;
  379. function TAppConfigRegistryProvider.ProcessPairRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
  380. var
  381. i : Integer;
  382. jValue : TJSONValue;
  383. RegValue : string;
  384. RegValueList : TStrings;
  385. RegKey : string;
  386. RegKeyList : TStrings;
  387. newObj : TJSONObject;
  388. begin
  389. newObj := TJSONObject.Create;
  390. //read root values
  391. RegValueList := TStringList.Create;
  392. try
  393. {$IFNDEF FPC}
  394. fRegConfig.GetValueNames(RegValueList);
  395. {$ELSE}
  396. try
  397. fRegConfig.GetValueNames(RegValueList);
  398. except
  399. end;
  400. {$ENDIF}
  401. for RegValue in RegValueList do
  402. begin
  403. newObj.AddPair(RegValue,ReadRegValue(cCurrentKey,RegValue));
  404. end;
  405. finally
  406. RegValueList.Free;
  407. end;
  408. //read root keys
  409. RegKeyList := TStringList.Create;
  410. try
  411. {$IFNDEF FPC}
  412. fRegConfig.GetKeyNames(RegKeyList);
  413. {$ELSE}
  414. try
  415. fRegConfig.GetKeyNames(RegKeyList);
  416. except
  417. end;
  418. {$ENDIF}
  419. for RegKey in RegKeyList do
  420. begin
  421. fRegConfig.OpenKeyReadOnly(cCurrentKey + '\' + RegKey);
  422. if IsRegKeyObject then
  423. begin
  424. jValue := ProcessPairRead(cCurrentKey + '\' + RegKey,Regkey,i);
  425. newObj.AddPair(RegKey,jValue);
  426. end
  427. else if IsRegKeyArray then
  428. begin
  429. jValue := ProcessElementRead(cCurrentKey + '\' + RegKey,Regkey,i);
  430. newObj.AddPair(RegKey,jValue);
  431. end
  432. else raise EAppConfig.Create('Unknow value reading Config Registry');
  433. end;
  434. finally
  435. RegKeyList.Free;
  436. end;
  437. Result := TJsonValue(newObj);
  438. end;
  439. function TAppConfigRegistryProvider.ProcessElementRead(const cCurrentKey, cRegKey : string; aIndex : Integer) : TJSONValue;
  440. var
  441. i : Integer;
  442. jValue : TJSONValue;
  443. RegValue : string;
  444. RegValueList : TStrings;
  445. RegKey : string;
  446. RegKeyList : TStrings;
  447. newObj : TJSONArray;
  448. begin
  449. newObj := TJSONArray.Create;
  450. //read root values
  451. RegValueList := TStringList.Create;
  452. try
  453. fRegConfig.GetValueNames(RegValueList);
  454. for RegValue in RegValueList do
  455. begin
  456. newObj.AddElement(ReadRegValue(cCurrentKey,RegValue));
  457. end;
  458. finally
  459. RegValueList.Free;
  460. end;
  461. //read root keys
  462. RegKeyList := TStringList.Create;
  463. try
  464. fRegConfig.GetKeyNames(RegKeyList);
  465. for RegKey in RegKeyList do
  466. begin
  467. fRegConfig.OpenKeyReadOnly(cCurrentKey + '\' + RegKey);
  468. if IsRegKeyObject then
  469. begin
  470. jValue := ProcessPairRead(cCurrentKey + '\' + RegKey,Regkey,i);
  471. newObj.AddElement(jValue);
  472. end
  473. else if IsRegKeyArray then
  474. begin
  475. jValue := ProcessElementRead(cCurrentKey + '\' + RegKey,Regkey,i);
  476. newObj.AddElement(jValue);
  477. end
  478. else raise EAppConfig.Create('Unknow value reading Config Registry');
  479. end;
  480. finally
  481. RegKeyList.Free;
  482. end;
  483. Result := TJsonValue(newObj);
  484. end;
  485. procedure TAppConfigRegistryProvider.ProcessPairWrite(const cCurrentKey: string; obj: TJSONObject; aIndex: integer);
  486. var
  487. jPair: TJSONPair;
  488. i : Integer;
  489. aCount: integer;
  490. begin
  491. jPair := obj.Pairs[aIndex];
  492. if IsSimpleJsonValue(jPair.JsonValue) then
  493. begin
  494. AddRegValue(cCurrentKey,jPair.JsonString{$IFNDEF FPC}.ToString{$ENDIF},jPair.JsonValue);
  495. Exit;
  496. end;
  497. if jPair.JsonValue is {$IFDEF FPC}fpjson.{$ENDIF}TJSONObject then
  498. begin
  499. aCount := TJSONObject(jPair.JsonValue).Count;
  500. for i := 0 to aCount - 1 do
  501. ProcessPairWrite(cCurrentKey + '\' + jPair.JsonString{$IFNDEF FPC}.ToString{$ENDIF}.DeQuotedString('"'), TJSONObject(jPair.JsonValue),i);
  502. end
  503. else if jPair.JsonValue is {$IFDEF FPC}fpjson.{$ENDIF}TJSONArray then
  504. begin
  505. aCount := TJSONArray(jPair.JsonValue).Count;
  506. for i := 0 to aCount - 1 do
  507. ProcessElementWrite(cCurrentKey + '\' + jPair.JsonString{$IFNDEF FPC}.ToString{$ENDIF}.DeQuotedString('"'), TJSONArray(jPair.JsonValue),i,aCount);
  508. end
  509. else raise EAppConfig.Create('Error Saving config to Registry');
  510. end;
  511. procedure TAppConfigRegistryProvider.ProcessElementWrite(const cCurrentKey: string; arr: TJSONArray; aIndex, aMax: integer);
  512. var
  513. jValue: TJSONValue;
  514. i : Integer;
  515. aCount: integer;
  516. dig : Integer;
  517. begin
  518. jValue := arr.Items[aIndex];
  519. dig := CountDigits(aMax);
  520. if IsSimpleJsonValue(jValue) then
  521. begin
  522. AddRegValue(cCurrentKey,Zeroes(aIndex,dig),jValue);
  523. Exit;
  524. end;
  525. if jValue is {$IFDEF FPC}fpjson.{$ENDIF}TJSONObject then
  526. begin
  527. aCount := TJSONObject(jValue).Count;
  528. for i := 0 to aCount - 1 do
  529. ProcessPairWrite(cCurrentKey + '\' + Zeroes(aIndex,dig),TJSONObject(jValue),i);
  530. end
  531. else if jValue is {$IFDEF FPC}fpjson.{$ENDIF}TJSONArray then
  532. begin
  533. aCount := TJSONArray(jValue).Count;
  534. for i := 0 to aCount - 1 do
  535. ProcessElementWrite(cCurrentKey + '\' + Zeroes(i,dig),TJSONArray(jValue),i,aCount);
  536. end
  537. else raise EAppConfig.Create('Error Saving config to Registry');
  538. end;
  539. { TAppConfigRegistry }
  540. constructor TAppConfigRegistry.Create(aHRoot : HKEY = HKEY_CURRENT_USER; const aMainKey : string = '');
  541. begin
  542. inherited Create(TAppConfigRegistryProvider.Create(aHRoot,aMainKey));
  543. end;
  544. destructor TAppConfigRegistry.Destroy;
  545. begin
  546. inherited;
  547. end;
  548. function TAppConfigRegistry.GetProvider: TAppConfigRegistryProvider;
  549. begin
  550. if not Assigned(fProvider) then raise EAppConfig.Create('No provider assigned!');
  551. Result := TAppConfigRegistryProvider(fProvider);
  552. end;
  553. end.