Recent

Author Topic: where to post new code for revision and sharing ? - TRegistryExtended  (Read 21840 times)

beefycoder

  • New Member
  • *
  • Posts: 24
As the title say ..

Where to post new code to be revised here ?

I have written a win-specific class that i wish to share
as open source, but also want some feedback for
usability, bugs etc ... (praise is also welcome ;) )
« Last Edit: December 09, 2010, 12:23:10 am by beefycoder »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8836
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: where to post new code for revision and sharing ?
« Reply #1 on: December 07, 2010, 06:55:59 pm »
It's OK to put here, some of us might be interested.

beefycoder

  • New Member
  • *
  • Posts: 24
Re: where to post new code for revision and sharing ?
« Reply #2 on: December 08, 2010, 02:18:30 am »
Ok first some introduction.

This class is an attempt to make access to windows registry functions more convinient to use and to address some, possibly subjective, shortcomings of the ones already supplied with lazarus/fpc distribution.

I admit i have only recently started to learn about classes, so the code i post will most likely look very plain and/or lacking wisdom, this is where constructive criticism, comments and ideas are welcome to help me improve it.

The initial reason is that i wanted to make a small registry scanning utility. I succeeded to use TRegistry class but have soon realized it lacked full range of abilities i needed to make such program. Namely, inability to use class members to retrieve REG_MULTI_SZ and some others. TRegistry class only supported rdString, rdExpandString, rdBinary, rdInteger (you can easily recognize REG_xxx equivalents).

I looked around for solution but have always come to same conclusion and advice given in this forum : use original TRegistry class and if needed, add missing functionality yourself.

And this would be for me a normal course of action so i have looked into the class organization to see what needs to be changed and/or added to make it work as i needed.

This attempt failed since i realized this class was spread over at least two units/files and had structure too complicated for my taste. I assume this is so to make it cross-platform, so some capabilities had to be removed. This compromise, combined with aforementioned complexity lead me to make my own registry class i dubbed TRegistryExtended to reflect some additions i made.

This class is made with following in mind:
-some operations are made automatic to ease usage
-it never keeps a lock on any handle in registry
-it assumes that some conditions must be fullfiled, thus it will raise exception in such instances
-it always tries to execute requested action and if it fails, it will return error and keep last good state
-it does not do any processing on data, only gives organized access to it, this means it will not only return raw data from windows API it will also give their return codes

Some basic ideas shown in TRegistry are retained and built upon.

The class itself has following public members :

* Constructor Create : overloaded, it can accept access type (KEY_xxx) or it can also receive root key in HKEY or string form. if it cannot complete, exception will be raised.

* Read property Status : status of last completed operation, not only original return code from windows API, but also from internal functions. This may be point of discussion as i am also not happy with this. I would like to try to define custom error codes that can be passed along same property.

* Read/write property Path : i was struggling with basic idea how this class should function to keep some complexity away from a programmer, ie to avoid the need to keep at all times a valid path to key.

* Read/write property RootH : HKEY version of root key. setting it "retargets" entire class to new root and resets path to blank.

* Read/write property RootS : string version, but otherwise same as HKEY before, for convinience only if programmer is doing some kind of text file I/O.

* Read/write property Access : access type. Can be changed at any time. Class does not assume if user wants to perform registry write operation to set access automatically to type of KEY_ALL_ACCESS or similar. Operation will fail if proper access is not set.

* Read property Key : for convinience, it is copy of last subkey in path string.

* Read property DateAccessed : in TDateTime format.

* Procedure GoParent : overloaded. Basic no-parameter-version sets path one key level up. With parameters, it accepts string in form of '\\\\' or '\\subkey\subkey' . Each backslash causes path to go one level up. If additional keys are supplied it will try to go up level then down
level.

* Procedure Refresh : nothing special. It only refreshes state of current path/key. Good for some basic tracking of changes. Not a replacement for more appropriate registry notification API.

* Procedure CreateKey : Creates a key under a current key. Requires subkey and Boolean determining if this key is to be set as currently working key. It only creates non-voltile keys !

* Procedure DeleteKey : Deletes a key. Requires path string argument and Boolean determining deletion of all subkeys. Path can be relative (with preceeding '\') or absolute (without preceeding '\'). I had to add declaration for SHDeleteKey from 'shlwapi.dll', or else i had to code a whole recursion procedure just for this  :)

* Function KeyExists : check for existance of key. Requires key name but it can formatted like path with '\' as first character in string denoting relative path. Returns Boolean. Does not affect status or cause any processing.

* Read property SubKeyCount : Integer number showing how many subkeys are present under a current key.

* Array read property SubKeyName : returns string name of subkey determined as integer.

* Array property SubKeyDate: returns TDateTime of subkey.

* Function ValueExists : same as KeyExists(), but needs value name string. Returns Boolean.

* Procedure DeleteValue : needs subkeyname and value name string.

* Procedure CreateValue : needs subkey name, value name, DWORD for value type, int for size and a pointer to a datablock. By providing "raw" access to underlying API, i avoided additional wrapping into some "my code". It's as raw as it can be.

* Read property ValueCount : int showing number of values inder current key.

* Read array property ValueName : like SubKeyName[] only for values.

* Read property ValueType : same as above.

* Read property ValueSize : same as above.

* Read property ValueData :  same as above, but pay attention this is a pointer to internally pre-alloced memory. do not try to FreeMem() it yourself !

Note also that all root/path changing and write/delete operations cause automatic refresh of current key and all date/subkey/value information that can be retrieved (available through RegEnumxxx () functions).

All subkeys and values are kept in internally allocated memory that is dynamically assigned as needed. I could have gone the TStringList route, but decided against it since i needed to be able to keep varied types of data and it had too much complexity for such a (IMHO) simple functioning.

Value data is kept in dynamically allocated typed blocks with pointers to actual value data.

Also note that i have done only minimal testing, speed and eventual memory leaking are not tested ! Createxxx() and Deletexxx() are not tested, mostly only reading-type functions. This one is first complete alpha, fresh as it gets !

So, here it (FINALLY :) ) comes, the actual source !
« Last Edit: December 08, 2010, 02:25:53 am by beefycoder »

beefycoder

  • New Member
  • *
  • Posts: 24
Re: where to post new code for revision and sharing ?
« Reply #3 on: December 08, 2010, 10:41:59 pm »
Leledumbo, got any opinion on my code ?

5 downloads so far, but no comments ? It is either flawless or horribly bad :)

Which one is it ? Please do tell !  :)

PS: If this needs to be moved to appropriate sub-forum, please moderators advise on moving this thread.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8836
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #4 on: December 09, 2010, 06:11:43 am »
It takes some time to read your post, and further read your code. I think I need 2-3 days.

fabienwang

  • Sr. Member
  • ****
  • Posts: 449
  • Lazarus is the best
    • My blog
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #5 on: December 09, 2010, 09:20:33 am »
hey beefycoder

I have just reviewed your code fastly.

First i think the idea is great and what you provide here can really help people that uses the registry.

I don't see anything horrible in the code ^^, i would just say be careful with your naming conventions.
For example, i see in the code:
if not (prStatus = ERROR_SUCCESS)
what is it, an error or a success? ^^

then in your 2 first constructors Create() and Create(aAccess: LongWord), i think you can remove the last part:
  SetRoot (HKEY_CURRENT_USER);

  if not (prStatus = ERROR_SUCCESS) then Raise ERegistryExtendedException.CreateFmt (RRegistryExtendedInvalidRootOrPathOnCreate, ['']);

In the method SetRoot, you're using some if:
      if aRoot = 'HKEY_CLASSES_ROOT' then prRoot := HKEY_CLASSES_ROOT;

      if aRoot = 'HKEY_CURRENT_USER' then prRoot := HKEY_CURRENT_USER;

      if aRoot = 'HKEY_LOCAL_MACHINE' then prRoot := HKEY_LOCAL_MACHINE;

      if aRoot = 'HKEY_USERS' then prRoot := HKEY_USERS;

      if aRoot = 'HKEY_CURRENT_CONFIG' then prRoot := HKEY_CURRENT_CONFIG;
while in the method GetRoot, you put a Case Of.

I suggest to use a Case Of when you have more than 2 consecutive IF.

Again, this is just a fast review (15min), and I haven't tested it.

Nice work :)
I'm using Arch Linux.
Known for: CPickSniff, OpenGrabby
Contributed to: LazPaint

beefycoder

  • New Member
  • *
  • Posts: 24
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #6 on: December 09, 2010, 11:23:50 am »
Thank you for responses and patience !

Leledumbo, yes i was impatient, reviewing other people's code does take time :)

Now about Fabiens' comments :

Quote
For example, i see in the code:
if not (prStatus = ERROR_SUCCESS)
what is it, an error or a success? ^^

This is a constant used by windows API. This is OS-specific, and people using other OSes get the impression something is wrong. So basically i do agree. But this is how it is defined and we (programmers) are stuck with it. I do want to add custom error codes, but i still haven't found out how and if it is possible. That way, programmers using this class could differentiate from return codes among API calls and my own.

Quote
then in your 2 first constructors Create() and Create(aAccess: LongWord), i think you can remove the last part:
  SetRoot (HKEY_CURRENT_USER);

This was a bit of a pickle ... At first i did copy structure from original TRegistry. The second overloaded constructor called it's first one. At first i did copy they worked, but as i added more functionality, i saw that when calling overloaded constructors in chain, SetRoot and other functions would get called multiple times, creating processing overhead at object creation time. So i decided to make each contructor do all of its work internaly and then call the TObject's basic constructor.

Quote
In the method SetRoot, you're using some if:
      if aRoot = 'HKEY_CLASSES_ROOT' then prRoot := HKEY_CLASSES_ROOT;

      if aRoot = 'HKEY_CURRENT_USER' then prRoot := HKEY_CURRENT_USER;

      if aRoot = 'HKEY_LOCAL_MACHINE' then prRoot := HKEY_LOCAL_MACHINE;

      if aRoot = 'HKEY_USERS' then prRoot := HKEY_USERS;

      if aRoot = 'HKEY_CURRENT_CONFIG' then prRoot := HKEY_CURRENT_CONFIG;
while in the method GetRoot, you put a Case Of.

I suggest to use a Case Of when you have more than 2 consecutive IF.

Multiple IF's are used instead CASE statement because CASE does not accept
values that are not constants and cannot be enumerated. Strings unfortunately do not fullfill this requirement (although it would be great to use strings for CASE comparisons). You can see that GetRoot uses CASE with windows constants, whereas SetRoot has overloaded version that accepts strings too.

Thank you all for the first-glance review !

Leledumbo

  • Hero Member
  • *****
  • Posts: 8836
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #7 on: December 09, 2010, 12:50:21 pm »
Quote
Multiple IF's are used instead CASE statement because CASE does not accept
values that are not constants and cannot be enumerated. Strings unfortunately do not fullfill this requirement
(although it would be great to use strings for CASE comparisons). You can see that GetRoot uses CASE with windows constants, whereas SetRoot has overloaded version that accepts strings too.
Ehm... see this (16) 8)

beefycoder

  • New Member
  • *
  • Posts: 24
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #8 on: December 09, 2010, 08:05:34 pm »
I already tried that. End result is

Code: [Select]
registryextended.pas(260,18) Error: Ordinal expression expected

On the line containing "case aRoot of" , where aRoot is of type string.

Maybe there is a compiler directive i don't know of that will make FPC "happy". So for now, this is how it works.

And i really don't want to get into wishlist given on that link, i work with IDE i got right now. Lazarus/FPC combo being a free alternative to Delphi with near complete feature set (there is always room for more) it is an offer hardly anyone can refuse.

fabienwang

  • Sr. Member
  • ****
  • Posts: 449
  • Lazarus is the best
    • My blog
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #9 on: December 09, 2010, 08:07:44 pm »
no. case string ... of is a fixed expression.

you should type "case string aRoot of"
I'm using Arch Linux.
Known for: CPickSniff, OpenGrabby
Contributed to: LazPaint

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #10 on: December 09, 2010, 08:28:54 pm »
Code: [Select]
begin
  case string edit1.Text of
    'Hallo', 'Hello': ShowMessage('Hallo');
    'Exit'          : Close;
  else
    ShowMessage('Unknown command: ' + edit1.Text);
  end;
end;   

Code: [Select]
unit1.pas(61,15) Error: Ordinal expression expected
unit1.pas(61,15) Fatal: Syntax error, "OF" expected but "identifier EDIT1" found

Lazarus 0.9.29 r27895 FPC 2.4.3 i386-win32-win32/win64

beefycoder

  • New Member
  • *
  • Posts: 24
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #11 on: December 10, 2010, 12:12:05 am »
I apologise i forgot to post a small project demonstrating some basic functionality
of my class (unit file is included).

Just do the following after compiling :
-select HKEYxxx
-click START
-select item in top list, look at results in middle and bottom
-then click some more in top list if want
-when done click STOP then QUIT

DirkS

  • Sr. Member
  • ****
  • Posts: 251
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #12 on: December 10, 2010, 02:19:16 am »
Code: [Select]
unit1.pas(61,15) Error: Ordinal expression expected
unit1.pas(61,15) Fatal: Syntax error, "OF" expected but "identifier EDIT1" found

Lazarus 0.9.29 r27895 FPC 2.4.3 i386-win32-win32/win64
Code: [Select]
case Edit1.Text ofworks with strings in FPC 2.5.1

Gr.
Dirk.

beefycoder

  • New Member
  • *
  • Posts: 24
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #13 on: December 10, 2010, 11:10:35 am »
DirkS, i did try before to update Lazarus from svn (i started a topic on it) but had no luck because i can't make heads or tails of the whole process. It was so confusing that i gave up on it (i could try it again inside VM, it won't touch my working setup) . All i can do now is wait for a new installer on SF download.

If there is a SANE way to update FPC from 2.2.4 to 2.5.1 inside Lazarus 0.9.28.2 beta, i'm willing to try it.

DirkS

  • Sr. Member
  • ****
  • Posts: 251
Re: where to post new code for revision and sharing ? - TRegistryExtended
« Reply #14 on: December 10, 2010, 11:57:20 am »
Quote
If there is a SANE way to update FPC from 2.2.4 to 2.5.1
More or less, but it took me a while to get that far...  ;)
I used the buildfaq as a start but made several modifications / extensions to suit my workflow and preferences.
If I have a bit more time I'll try to describe how I managed it under WinXP.

Gr.
Dirk.

 

TinyPortal © 2005-2018