2016-06-06 9 views
0

Betrachten Sie das folgende:TRegistry :: KeyExists() schlägt fehl, wenn Schlüsselräume hat

TRegistry* registry = new TRegistry(); 
registry->RootKey = HKEY_LOCAL_MACHINE; 
registry->Access = KEY_READ; 

if (true == registry->KeyExists("Software\\Abc\\My Key")) // note the space 
{ 
    // read 
} 
else 
{ 
    // error 
} 

Der obige Fall wird in else Block gehen. Ich schätze, das Problem liegt an dem Platz, der im Schlüssel vorhanden ist. Oder ist es etwas anderes? Beachten Sie, dass ich "Software\\Abc" erfolgreich lesen kann.

Ich habe bereits versucht, doppelte Anführungszeichen verwenden, wie folgt aus:

if (true == registry->KeyExists("\"Software\\Abc\\My Key\"")) 
{ 
    .... 
} 

aber alles vergebens.

Irgendwelche Kabel?

Antwort

0

Ihr erstes Beispiel ist vollkommen in Ordnung und korrekt. Sie müssen keine zusätzlichen Anführungszeichen um Zeichenfolgen mit Leerzeichen einfügen. Registrierungsschlüsselnamen können Leerzeichen enthalten, und wenn Sie tatsächlich in der Registrierung nachsehen, werden Sie tatsächlich die Schlüssel überall sehen, die Leerzeichen in ihnen haben.

KeyExists() testet das Vorhandensein, indem der angegebene Schlüssel tatsächlich geöffnet und dann geschlossen wird. Wenn KeyExists() false zurückgibt, bedeutet dies, dass TRegistry den angegebenen Schlüssel nicht öffnen konnte.

KeyExists() ignoriert den aktuellen Access Eigenschaftswert (außer der Verwendung einer bestimmten KEY_WOW64 Flag). Es verwendet seine eigenen Access Flags, speziell STANDARD_RIGHTS_READ, KEY_QUERY_VALUE und KEY_ENUMERATE_SUB_KEYS. Wenn also KeyExists() false zurückgibt, ist der Schlüssel entweder nicht vorhanden oder der aufrufende Thread hat keine Sicherheitsrechte, um den Schlüssel mit diesen Berechtigungen zu öffnen (was beim Zugriff auf Schlüssel in HKEY_LOCAL_MACHINE nicht unbekannt ist). Leider

, hat KeyExists() nicht aktualisieren, um die TRegistry::LastError Eigenschaft (wenn Sie eine Version von C++ Builder verwenden, der diese Eigenschaft zur Verfügung hat), so dass man nicht unterscheiden kann, warum KeyExists() falsch zurückkehrt. Wenn Sie überprüfen möchten, ob der Zielschlüssel vorhanden ist, ohne den Schlüssel selbst zu öffnen, können Sie den übergeordneten Schlüssel zuerst öffnen und dann GetKeyNames() anrufen, um eine Liste seiner Unterschlüssel zu erhalten und dann nachsehen, ob Ihr Zielschlüssel vorhanden ist In der Liste. Dies erfordert natürlich Sicherheitszugriff auf den übergeordneten Schlüssel.

Da KeyExists() tatsächlich den Schlüssel öffnet, wäre ein anderer Weg, den Schlüssel einfach selbst zu öffnen (besonders wenn Sie tatsächlich Werte aus dem Schlüssel lesen möchten). Verwenden Sie OpenKeyReadOnly() für das, zB:

TRegistry* registry = new TRegistry(); 
registry->RootKey = HKEY_LOCAL_MACHINE; 

// only if needed: 
registry->Access = KEY_WOW64_32KEY; // or KEY_WOW64_64KEY 

if (registry->OpenKeyReadOnly("Software\\Abc\\My Key")) 
{ 
    // read... 

    registry->CloseKey(); 
} 
else 
{ 
    // error 
} 

Die Vorteile, dies zu tun sind, dass:

  1. OpenKeyReadOnly() (und OpenKey()) aktualisiert die LastError Eigenschaft.

  2. OpenKeyReadOnly() versucht mehrere verschiedene Kombinationen von Access Flags, um eine bessere Chance zu haben, tatsächlich den Schlüssel zum Lesen zu öffnen.Während der Einnahme WOW64 berücksichtigt, es:

    1. erste Versuche KEY_READ, die eine Kombination aus STANDARD_RIGHTS_READ ist, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS und KEY_NOTIFY, minus SYNCHORNIZE.

    2. Wenn das fehlschlägt, versucht es dann STANDARD_RIGHTS_READ, KEY_QUERY_VALUE und KEY_ENUMERATE_SUB_KEYS (gleich wie KeyExists()).

    3. Wenn das fehlschlägt, versucht es dann KEY_QUERY_VALUE von selbst. Wenn der Schlüssel tatsächlich existiert, ist dies normalerweise erfolgreich, sofern keine Sicherheitsrichtlinie vorhanden ist, die den Lesezugriff ausdrücklich verweigert.

    4. Wenn das fehlschlägt, gibt es auf.

Wie alles andere in Windows-Sicherheit, sollten Sie nur das Nötigste Berechtigungen anzufordern streben, die Sie tatsächlich benötigen, nicht mehr als das. Zum Beispiel, wenn Sie in den Schlüssel lesen Werte benötigen, müssen aber nicht Subkeys zugreifen, könnte man alternativ tun Sie stattdessen:

TRegistry* registry = new TRegistry(); 
registry->RootKey = HKEY_LOCAL_MACHINE; 
registry->Access = KEY_QUERY_VALUE; // and KEY_WOW64_32KEY/KEY_WOW64_64KEY if needed 

if (registry->OpenKey("Software\\Abc\\My Key", false)) 
{ 
    // read... 

    registry->CloseKey(); 
} 
else 
{ 
    // error 
} 

Obwohl in der Regel sollten Sie mit OpenKeyReadOnly() haften, wenn Sie den Zugriff müssen lesen, es sei denn, Sie brauchen unbedingt mehr Kontrolle über die Access Flags, dann verwenden Sie stattdessen OpenKey().