[C++] Registry auslesen

06/15/2011 15:02 .Infinite#1
Ich suche nach einer Möglichkeit, Zeichenfolgen(REG_SZ) aus der Windows Registry auszulesen.

Geeignet dafür sind die Funktionen RegOpenKeyEx und RegQueryValueEx von der WinAPI... Allerdings weiß ich nicht, wie ich damit Zeichenfolgen auslesen kann. Alle Beispiele, die ich dazu finden konnte waren auf DWORD bezogen.
06/15/2011 15:51 xNopex#2
Der fünfte Parameter von RegQueryValueEx() legt den Buffer fest, in den die Daten gespeichert werden. Es handelt sich dabei um ein BYTE-Array, wie du sicher der Dokumentation entnommen hast. BYTE ist eine von Windows definierte Datenstruktur und nichts anderes als ein unsigned char. Damit hast du deine Zeichenkette.
06/15/2011 18:09 .Infinite#3
Also irgendwie klappt das immer noch nicht. Wenn ich den buffer ausgebe kommt immer so etwas wie 001CFB78. Und der Wert ist jedesmal anders...

Das gleiche Ergebnis habe ich, wenn ich die Registry-Klasse aus der ATL nehme (CRegKey)
06/15/2011 18:48 xNopex#4
Du gibst den Buffer auf der Konsole oder wo auch immer vermutlich falsch aus. Das sieht aus, als ob du anstatt den Inhalt eines Pointers, die Adresse des Pointers ausgibst.

Code:
char buffer[128];
ZeroMemory(buffer, 128);
.
.
.
std::cout.write(buffer, strlen(buffer));
EDIT:
Ich habe mich mal erbarmt und dir ein komplettes Beispiel erstellt:
Code:
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    HKEY hKeyValue = NULL;
    long ret = RegOpenKeyEx(HKEY_USERS, ".DEFAULT\\Environment", 0, KEY_READ, &hKeyValue);
    if(ret != ERROR_SUCCESS)
    {
        cout << "RegOpenKeyEx failed. Error code: " << GetLastError();
        return 1;
    }

    DWORD bufferLen = 128;
    BYTE buffer[bufferLen];
    ret = RegQueryValueEx(hKeyValue, "TEMP", NULL, NULL, buffer, &bufferLen);
    if(ret != ERROR_SUCCESS)
    {
        cout << "RegQueryValueEx failed. Error code: " << GetLastError();
        return 1;
    }
    buffer[bufferLen] = 0;
    cout.write((const char*)(buffer), bufferLen);
    return 0;
}
06/16/2011 14:42 .Infinite#5
Danke! Es funktioniert jetzt auf jeden Fall...

Ich habe aber trotzdem noch ein paar Fragen und Anmerkungen zum Verständnis. Vielleicht hilft es ja auch anderen.

PHP Code:
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    
HKEY hKeyValue NULL// mit null initialisieren ist unnötig oder? //
    
long ret RegOpenKeyEx(HKEY_USERS".DEFAULT\\Environment"0KEY_READ, &hKeyValue);
    if(
ret != ERROR_SUCCESS)
    {
        
cout << "RegOpenKeyEx failed. Error code: " << GetLastError();
        return 
1;
    }

    
DWORD bufferLen 128// warum 128? //
    
BYTE buffer[bufferLen];  // ließ sich bei mir nicht kompilieren. Da muss eine Konstante rein //
    
ret RegQueryValueEx(hKeyValue"TEMP"NULLNULLbuffer, &bufferLen);
    if(
ret != ERROR_SUCCESS)
    {
        
cout << "RegQueryValueEx failed. Error code: " << GetLastError();
        return 
1;
    }
    
buffer[bufferLen] = 0// warum den string mit null terminieren? funktionieren tut es auch ohne //
    
cout.write((const char*)(buffer), bufferLen);
    return 
0;

Außerdem musste ich bei mir immer vor dem Pfad des Schlüssels und dem Namen das Makro _T benutzen, sonst gab es einen Fehler mit den Typen.
Und bei der Ausgabe sind zwischen den Buchstaben immer Leerzeichen. Auch komisch...
06/16/2011 15:03 xNopex#6
Quote:
HKEY hKeyValue = NULL; // mit null initialisieren ist unnötig oder? //
Lieber einmal zu viel mit NULL einen Pointer ungültig machen, als dass man zur Runtime einen Error bekommt. Das ist guter Stil.

Quote:
DWORD bufferLen = 128; // warum 128? //
Die Zahl ist beliebig. Ich habe den Buffer halt mal 128Zeichen groß gemacht. Dachte das wird genügen. Man kann ihn aber auch größer/kleiner machen.

Quote:
BYTE buffer[bufferLen]; // ließ sich bei mir nicht kompilieren. Da muss eine Konstante rein //
Kommt davon, wenn man den Microsoft-Compiler verwendet :) MinGW meckert nicht. Beim Microsoft Compiler müsstest du es so machen:
Code:
DWORD bufferLen = 128;
BYTE buffer[128];
Du darfst hierbei 'bufferLen' nicht als Konstante setzen, da du sie später als in/out Pointer an RegQueryValueEx() übergibst.

Quote:
buffer[bufferLen] = 0; // warum den string mit null terminieren? funktionieren tut es auch ohne //
Terminieren tut man ein C-String eigentlich immer. Dass es bei dir auch ohne funktioniert, liegt wohl einfach daran, dass der Compiler dafür gesorgt hat, dass der Speicher zuvor mit '0' aufgefüllt wurde. vgl. ZeroMemory().

Quote:
Außerdem musste ich bei mir immer vor dem Pfad des Schlüssels und dem Namen das Makro _T benutzen, sonst gab es einen Fehler mit den Typen.
Und bei der Ausgabe sind zwischen den Buchstaben immer Leerzeichen. Auch komisch...
Das liegt daran, dass du Unicode verwendest und ich Ansi. Entweder du stellst das in den Projekteinstellungen um, oder du verwendest anstatt "char" "wchar_t" und "wcout" anstatt "cout".
06/16/2011 16:30 5769854332#7
für REG_SZ könnte man auch RegGetValue benutzen.

Quote:
To ensure that any string values (REG_SZ, REG_MULTI_SZ, and REG_EXPAND_SZ) returned are null-terminated, use the RegGetValue function.
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...]
06/19/2011 00:58 SmackJew#8
Quote:
Originally Posted by .Infinite View Post
HKEY hKeyValue = NULL; // mit null initialisieren ist unnötig oder? //
Initialisierst du deine Variablen nicht, machst du nichts anderes als den Stackpointer zu versetzen. Die Daten die dann dort liegen sind im Grunde willkürlich (was auch immer da vorher auf dem Stack lag). Wenn du durch irgendeine Unachtsamkeit dann den Wert liest und ggf. weiter damit arbeitest erhältst du willkürliche Ergebnisse. Das kann Fehler erzeugen von einfacher Verschmierung deiner Daten bis zu Speicherverletzungen. Wenn du deine Variablen mit sinnvollen Werten bzw. 0 initialisierst hast du diese Probleme nicht, bzw. hast es einfacher die Ursache aufzuspüren.