当key有空格时,TRegistry :: KeyExists()失败

时间:2016-06-06 09:52:00

标签: registry c++builder

请考虑以下事项:

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 
}

上述情况将进入else块。我想问题是因为密钥中存在空间。或者是别的什么?请注意,我能够成功阅读"Software\\Abc"

我已经尝试过使用双引号,如下所示:

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

但都是徒劳。

任何线索?

1 个答案:

答案 0 :(得分:0)

你的第一个例子非常精细和正确。您不需要在带有空格的字符串周围添加额外的引号。注册表项名称中可以包含空格,如果您实际查看注册表,实际上会看到所有地方的键,其中包含空格。

KeyExists()通过实际打开指定的键然后关闭它来测试存在。当KeyExists()返回false时,表示TRegistry无法打开指定的密钥。

KeyExists()忽略当前Access属性值(除了使用任何指定的KEY_WOW64标志之外)。它使用自己的Access标记,特别是STANDARD_RIGHTS_READKEY_QUERY_VALUEKEY_ENUMERATE_SUB_KEYS。因此,当KeyExists()返回false时,密钥实际上不存在,或者更有可能调用线程没有安全权限来打开具有这些权限的密钥(这在访问{{1时的密钥时并非闻所未闻) }})。

不幸的是,HKEY_LOCAL_MACHINE不会更新KeyExists()属性(如果您使用的是具有该属性的C ++ Builder版本),那么您就无法区分原因TRegistry::LastError 1}}返回false。

如果你想检查目标密钥是否存在而没有实际打开密钥本身,一种方法是首先打开父密钥,然后调用KeyExists()获取其子密钥列表,然后查看是否目标键在列表中。当然,这需要对父密钥进行安全访问。

由于GetKeyNames()实际上打开了密钥,另一种方法是自己简单地打开密钥(特别是如果您计划实际读取密钥中的值)。请使用KeyExists(),例如:

OpenKeyReadOnly()

这样做的好处是:

  1. 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 } (和OpenKeyReadOnly())更新OpenKey()属性。

  2. LastError尝试几种不同的OpenKeyReadOnly()标记组合,以便更有可能实际打开阅读键。考虑到WOW64,它:

    1. 首次尝试Access,这是KEY_READSTANDARD_RIGHTS_READKEY_QUERY_VALUEKEY_ENUMERATE_SUB_KEYS的组合,减去KEY_NOTIFY

    2. 如果失败,则会尝试SYNCHORNIZESTANDARD_RIGHTS_READKEY_QUERY_VALUE(与KEY_ENUMERATE_SUB_KEYS相同)。

    3. 如果失败,则会自行尝试KeyExists()。如果密钥实际存在,这通常会成功,除非有明确拒绝读取访问权限的安全策略。

    4. 如果失败,它会放弃。

  3. 与Windows安全性中的任何其他内容一样,您应该努力仅请求您实际需要的最低权限,不多于此。例如,如果您需要读取密钥中的值,但不需要访问子密钥,则可以选择执行此操作:

    KEY_QUERY_VALUE

    虽然您通常应该在需要阅读权限时坚持使用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 } ,除非您绝对需要对OpenKeyReadOnly()标记进行更多控制,否则请改用Access