Sources update
The sources have been updated. (Hopefully) This will make them compilable on VC 7+.
I couldn't test it with VC 7, but I expect it will be OK now.
For more info take a look what was the problem.
New Additions
This class has been modified:
- Improved internal logic.
- Improved support for writing structured data to registry.
- Added possibility to see internal execution flow (e.g., when data is read from and written to the registry).
- Added support for
HKEY_LOCAL_MACHINE
, HKEY_USERS
, and all the others...
In short, in order to store a structure in registry, you only need to do like this:
SomeStruct X;
reg["SomeStructData"].set_struct(X);
In order to read back the stored structure:
SomeStruct X;
if(reg["SomeStructData"].get_struct(X)){
}else {
}
In order to use HKEY_LOCAL_MACHINE
or other, you can pass a second parameter of type registry::Key
to the registry constructor:
registry reg("Sowtware\\Whatever",registry::hkey_local_machine);
The second parameter is optional, it defaults to registry::hkey_current_user
.
In order to see internal execution flow, you may #define WANT_TRACE
. And in console mode, you'll see when and what objects are created, and when values read to/ written from the registry. There was added a new project with_trace to see that.
#define WANT_TRACE
#include "registry.h"
#include "string.h"
#include <STRING>
struct Something{
int area;
float height;
};
int main(int, char*)
{
registry reg("Software\\Company");
{
Something X;
X.area=100;
X.height=4.5;
reg["Something"].set_struct(X);
}
Something Z;
if(reg["Something"].get_struct(Z)){
printf("area is: %i\nheight is: %f\n", Z.area,Z.height);
}
return 0;
}
It produces the following output:
Introduction
First of all, you need only one file registry.h, that's included in the source distribution. Read on...
#include "registry.h"
#include "string.h"
int main(int, char*){
registry reg("Software\\Company");
reg["Language"]="English";
reg["Width"]=50;
printf("The address is: %s\n",(char*)reg["Address"]);
return 0;
}
A more descriptive howto:
#include "registry.h"
#include "string.h"
struct ServerAddress{
char name[64];
char ip[15];
short port;
};
int main(int,char*){
registry settings("Software\\MyCoolApp");
if(!settings){
exit(1);
}
registry::iterator lang=settings["Language"];
printf("The selected language is: \"%s\"\n",(char*)lang);
lang="Russian";
ServerAddress MyCoolServer;
strcpy(MyCoolServer.name,"somewhere.example.com");
strcpy(MyCoolServer.ip,"192.168.0.1");
MyCoolServer.port=1024;
registry::iterator server=settings["server"];
server=string((const char *)(&MyCoolServer),sizeof(MyCoolServer));
ServerAddress serAdr;
const string &FromRegistry=server;
if(FromRegistry.length()==sizeof(ServerAddress)){
memcpy(&serAdr,FromRegistry.c_str(), sizeof(ServerAddress));
printf("Print out for my server:\n");
printf("\tserver's host name is: %s\n", serAdr.name);
printf("\tserver's ip address is: %s\n", serAdr.ip);
printf("\tserver's port is: %u\n\n", serAdr.port);
}else{
}
return 0;
}
Pic.1 Output from a more descriptive howto.
I coded these few lines with simplicity in mind. I like the style, when I can assign value to a registry key as to a usual variable. I will describe shortly how I use this code in my projects. I put a member variable reg
(instance of registry) to my app's class (there is a reason, read below) that needs access to the registry. Then, in the class' constructor, I instantiate reg
variable to the registry home key. Since there is no default constructor in the registry class, you may do it like this:
class my_app{
protected:
registry reg;
string UserName;
public:
my_app() : reg("Software\\my_app"){
UserName = reg["UserName"];
}
~my_app(){
reg["UserName"] = UserName;
}
}
In the preceding line, you actually don't need to create a separate string for UserName
- you may have a member variable of registry::iterator
type, that will be automatically stored to the registry when your class is destructed (see the final example at the bottom of the page).
And then, whenever you need, you can do like this:
SetLanguage(reg["Lang"]);
string UserName=reg["User"];
that's really simple...
Background
Now, a little background on how it works internally. This is actually a very lightweight class. It makes less API calls than you would probably do.
For example, the line:
reg["Something"]="nothing";
will only once physically access registry on destruction of the returned key-value to assign value "nothing" to key "something".
Same happens with the next lines (only one API call when the group goes out of scope):
registry::iterator name=settings["UserName"];
name="John";
name="Alex";
name="Someone Else";
Basically, if you intend to use this class, you should be aware that statement reg["something"]="nothing";
doesn't modify anything in registry by itself. The value will be set only when the statement goes out of scope, like this:
{
reg["UserName"]="Bill";
printf("The username is: %s\n", (char*)reg["UserName"]);
}
printf("The username is: %s\n", (char*)reg["UserName"]);
In order to force it to commit to the registry at some point, you can use flush()
method like this:
registry::iterator name=settings["UserName"];
name="John";
name.flush();
The same applies to reading values - they are retrieved only when you request them, and only once! So, if you know (or think) that something else (perhaps Earth's magnetic field :)) has modified a key's value, you may use refresh()
method. But, be carfull!! Anything you have assigned before will not be committed (it's overwritten by the returned value from registry).
And a very important point. When the instance of registry is destructed, or goes out of scope, then all the values you created from it will not have access to the registry. That is, all iterators on a given registry instance should be destructed before their parent registry instance. That's why I use this class as a member of another class. When the parent class is destroyed, it doesn't need access to the registry, neither is it possible at that point.
That's it. Hope it will be useful to someone.
A better example
#include "registry.h"
#include <iostream>
class my_app{
protected:
registry reg;
registry::iterator UserName;
public:
my_app():reg("Software\\Company"),UserName(reg["UserName"]){}
~my_app(){}
void SetUserName(const char * name){
UserName = name;
}
const char * GetUserName(){
return (const char *) UserName;
}
};
int main (int, char *){
my_app App;
App.SetUserName("Alex");
cout<<"The username is: "<<App.GetUserName()
<<endl<<"Thanks for playing..."<<endl;
return 0;
}