Download

reg.zip (15.350 Byte)

Warum?

Irgendwann war es soweit: Ich musste einige Werte in der Registry speichern und natürlich auch wieder lesen. Also habe ich mir die API-Funktionen angesehen und wurde etwas blass. Dann habe ich mich im Internet umgesehen, in der Hoffnung, dass jemand so nett war und eine Klasse um diese Horror-Funktionen herum geschrieben und ins Netz gestellt hat. Jemand hatte. Aber die eine Klasse wollte sich erst gar nicht kompilieren lassen, die andere schrieb alles, ob String oder bool als Binärwert in die Registry und wieder eine andere hatte ein schreckliches Interface. Also mußte ich selber ran.

Ziel war es für mich, mir bei der Benutzung meiner Klasse möglichst viel Arbeit zu sparen. Hinterher sollten Werte in der Registry stehen, die auch menschenlesbar sind und sich dann evtl. auch von Hand mit REGEDIT ändern lassen.

Achtung!

Stellt man mit der Registry dumme Dinge an, dann kann sich das furchtbar rächen. Im schlimmsten Fall muß man das Betriebssytem neu installieren.

Deshalb:

Außerdem muß ich zugeben, daß ich keine Ahnung von Windows NT oder 2000 habe. Deshalb kann ich auch nicht sagen, ob CRegistry auf diesen Betriebssytemen läuft und wenn ja, unter welchen Voraussetzungen.

Zur Terminologie:

Am besten verdeutlicht man sich die Begriffe, indem man an die Ansicht denkt, die REGEDIT einem von der Registry bietet. Alles was links in der Baumstruktur steht sind KEYS (Schlüssel). Auf der rechten Seite, den Keys untergeordnet, finden sich VALUES (Werte).

News

25. August 2002: Wieder zwei Bugs weniger: Der aktuelle Pfad in der Registry wurde nur in den seltensten Fällen korrekt gespeichert. Jetzt kann man ihn sinnvoll abfragen und bekommt dabei auch noch Informationen über den geöffneten Stammzweig. Außerdem: Die Methoden EnumKeys() und EnumValues() ließen sich nur einmal pro Programmlauf nutzen (Ich setzt mich jetzt hin und schreibe 100 mal "Statische Member sind böse!").

3. Juli 2002: Gerade habe ich einen grausigen Bug entdeckt: CRegistry hat bisher alle neuen Werte mit der Option REG_OPTION_VOLATILE gespeichert. Auf NT und Nachfolgern führte das dazu, daß die neuen Werte nach dem nächsten Booten wieder verschwunden waren. Jetzt wird die Option REG_OPTION_NON_VOLATILE verwendet und neue Werte sollten persistent sein.

2. Juli 2002: Ich habe der Klasse zwei neue Methoden spendiert:
bool CRegistry::EnumKeys (CString &keyname) Listet alle Unterschlüssel des gerade geöffneten Schlüssels auf. Dazu ruft man die Methode auf, bis sie falsezurückgibt. Als Argument gibt man einen CString an, der nach einem erfolgreichen Aufruf (Rückgabewert: true) den Namen eines Unterschlüssels enthält.
bool CRegistry::EnumValues (CString &valuename, int &type) zählt die Werte des geöffneten Schlüssels auf. Auch diese Methode ruft man auf bis sie false zurückgibt. Zusätzlich zu dem CString, der dann den Namen des Werts enthalten wird, gibt man noch einen int mit an, der den Typ des Werts enthalten wird. Die möglichen Werte für den Typ sind in der MSDN bei der Funktion RegEnumValue() dokumentiert.

Beispiele:

Erstens

Ich will, dass Dateien mit der Extension .ABC mit meinem Programm verknüpft werden. Mein Programm ist dabei "c:\prog\prog.exe", den Dateien möchte ich den Namen "ProgDats" verpassen:

Zuerst erstelle ich mir also ein CRegistry-Objekt und gebe dem Konstruktor gleich den zu öffnenden Key mit:

CRegistry reg (HKEY_CLASSES_ROOT);

Jetzt prüfe ich, ob die Endung .ABC bereits verknüpft ist:

bool gibtsschon = reg.HasKey (".abc");

Falls ja, dann öffne ich den Schlüssel und seh mal nach, welcher Dokumententyp das ist:

reg.Open (".abc");
CString type;
reg.Read ("", type);

Jetzt habe ich den Typ und kann mich nach der zugehörigen Anwendung erkundigen:

if (!type.IsEmpty())
   if (reg.Open (HKEY_CLASSES_ROOT, type))
   {
      reg.Open ("shell\\open\\command");
      CString app;
      reg.Read ("", app);
   }

Jetzt kann ich den Benutzer fragen (sollte ich zumindest), ob ich die Verknüpfung überschreiben darf. Falls ja, lasse ich den alten Dokumententyp stehen und setze meinen eigenen auf ".abc":

reg.Open (HKEY_CLASSES_ROOT, ".abc");
reg.Write ("", "ProgDats");

Fehlt nur noch die Anweisung mit der man eine Datei vom Typ ProgDats öffnet:

reg.Open (HKEY_CLASSES_ROOT);
reg.CreateKey ("ProgDats\\shell\\open\\command");
reg.Write ("", "C:\\PROG\\PROG.EXE \"%1\"");

... und das sollte es gewesen sein!

Zweitens:

Für meine Anwendung möchte ich einen Schlüssel in HKEY_CURRENT_USER\Software erstellen, und unter diesem Schlüssel möchte ich die Daten speichern, die sich mein Programm von Aufruf zu Aufruf merken soll:

Zuerst erstelle ich mir wieder ein CRegistry-Objekt:

CRegistry reg (HKEY_CURRENT_USER, "Software");

Jetzt sollte ich prüfen, ob es schon einen Schlüssel gibt, der wie meiner heißt (mit CRegistry::HasKey), aber ich übergehe das hier und erzeuge den Schlüssel gleich:

reg.CreateKey ("Prog");

Ich will, dass die folgenden Werte gespeichert werden:

Das sollte erstmal reichen. Die Werte müssen jetzt nur noch geschrieben werden:

reg.Write ("Position", place);
reg.Write ("Option", option);
reg.Write ("Dateien", mru);

Billig. In Regedit sollte das ganze jetzt so aussehen:

HKEY_CURRENT_USER
  Software
    ...
    Prog  (Standard)          (Wert nicht gesetzt)
          Dateien count       0x00000001 (1)
          Dateien 1           "C:\temp\test.abc"
          Option              "false"
          Position flags      0x00000002 (2)
          Position normalPos  "5, 5, 600, 460"
          Position ptMax      "-1, -1"
          Position ptMin      "0, 0"
          Position showCmd    0x00000003 (3)
    ...

So werden aus drei Zeilen Code also jede Menge Werte in der Registry, die man auch mit dem bloßen Auge (==REGEDIT.EXE) lesen kann.

Referenz

Ein kurze Erklärung für jede Funktion in CRegistry ist zur Zeit leider nur auf Englisch verfügbar.

Lizenz

Der Code zu CRegistry ist Freeware. Macht damit, was Ihr wollt, aber lasst bitte meinen Namen in der Header-Datei stehen. Falls Ihr CRegistry benutzt, würde ich mich über eine kleine Nachricht freuen. Genauso sieht es mit Verbesserungsvorschlägen und Bugreports aus.