请考虑以下事项:
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\""))
{
....
}
但都是徒劳。
任何线索?
答案 0 :(得分:0)
你的第一个例子非常精细和正确。您不需要在带有空格的字符串周围添加额外的引号。注册表项名称中可以包含空格,如果您实际查看注册表,实际上会看到所有地方的键,其中包含空格。
KeyExists()
通过实际打开指定的键然后关闭它来测试存在。当KeyExists()
返回false时,表示TRegistry
无法打开指定的密钥。
KeyExists()
忽略当前Access
属性值(除了使用任何指定的KEY_WOW64
标志之外)。它使用自己的Access
标记,特别是STANDARD_RIGHTS_READ
,KEY_QUERY_VALUE
和KEY_ENUMERATE_SUB_KEYS
。因此,当KeyExists()
返回false时,密钥实际上不存在,或者更有可能调用线程没有安全权限来打开具有这些权限的密钥(这在访问{{1时的密钥时并非闻所未闻) }})。
不幸的是,HKEY_LOCAL_MACHINE
不会更新KeyExists()
属性(如果您使用的是具有该属性的C ++ Builder版本),那么您就无法区分原因TRegistry::LastError
1}}返回false。
如果你想检查目标密钥是否存在而没有实际打开密钥本身,一种方法是首先打开父密钥,然后调用KeyExists()
获取其子密钥列表,然后查看是否目标键在列表中。当然,这需要对父密钥进行安全访问。
由于GetKeyNames()
实际上打开了密钥,另一种方法是自己简单地打开密钥(特别是如果您计划实际读取密钥中的值)。请使用KeyExists()
,例如:
OpenKeyReadOnly()
这样做的好处是:
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()
属性。
LastError
尝试几种不同的OpenKeyReadOnly()
标记组合,以便更有可能实际打开阅读键。考虑到WOW64,它:
首次尝试Access
,这是KEY_READ
,STANDARD_RIGHTS_READ
,KEY_QUERY_VALUE
和KEY_ENUMERATE_SUB_KEYS
的组合,减去KEY_NOTIFY
如果失败,则会尝试SYNCHORNIZE
,STANDARD_RIGHTS_READ
和KEY_QUERY_VALUE
(与KEY_ENUMERATE_SUB_KEYS
相同)。
如果失败,则会自行尝试KeyExists()
。如果密钥实际存在,这通常会成功,除非有明确拒绝读取访问权限的安全策略。
如果失败,它会放弃。
与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
。