c ++正确读写windows注册表

时间:2010-08-05 09:16:15

标签: windows visual-c++ registry bho

所以我已经坚持了一段时间......以为我得到了它的工作,但它有时会中断,我不确定原因......

我不确定这是否重要,但我在浏览器帮助程序对象(BHO)中写这个...... IE总是32位进程,无论它是在64位还是32位操作系统上运行?

所以我希望能够从注册表中读取,这是我可能需要创建的一个键...

我使用这个功能:

if (RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\ProductName", 0, NULL,
                   REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_32KEY,
                   NULL, &hk, NULL) == ERROR_SUCCESS)

然后我检查密钥是否存在:

TCHAR ext_id[20];
DWORD toolbarIdLength;

if(RegQueryValueEx(hk, L"ext_id", NULL, NULL,
                   (LPBYTE)ext_id, &extIdLength) == ERROR_SUCCESS)

如果成功,那么我确保它是空终止的:

ext_id[extIdLength] = 0;

否则我使用wininet lib将信息发送到我的服务器,分配新的ext_id并写入注册表这个值......使用此函数:

RegSetValueEx(hk, L"ext_id", 0, REG_SZ, (const BYTE *)ext_id, _tcslen(ext_id)*2 + 1);

由于一些奇怪的原因,它只写了我传递的一半东西所以我加倍_tcslen(ext_id)并为安全添加1?我在网上找到的大多数例子没有那个长度乘以2,它对我来说就像这样,所以我把它留下了......

似乎这一切都运作正常:

它适用于我的dev_machine:Windows 7 64位。

在32位Windows 7上测试...

问题出现在Windows XP IE 6上,它没有用,但似乎如果我再次调用RegQueryValueEx函数,它会返回正确的值,所以我注意到下一个请求......

我还注意到,根据我发送给服务器的其他字符串,它会有不同的工作方式,这可能是因为我对C ++相对较新,(实际上只有几周)而且我是我确定我做错了什么。

哦,我在msdn上读到我需要在标志中使用KEY_WOW64_32KEY或KEY_WOW64_64KEY,这取决于具体情况......但在我的情况下这是非常必要的(浏览器6.0到8.0的BHO)

1 个答案:

答案 0 :(得分:0)

你已经对Windows如何处理unicode感到沮丧。 Dev Studio有一个方便的开关,允许您在应用程序的Unicode和多字节构建之间切换,并且您正在为Unicode构建。

位置是项目属性 - 配置属性 - 常规 - 字符集:使用Unicode字符集。

所有字符串文字前面的L表示字符串文字是wchar_t的数组:L“Software \ ProductName”。

TCHAR是一个宏,在构建多字节字符集应用程序时为unicode和`char1构建时意味着wchar_t

_tcslen同样是一个MACRO,msv c-runtine定义为strlen或wcslen,具体取决于项目选择的字符集。

无论如何,问题的关键是:wcslen返回字符串中wchar_t的数量,注册表函数需要数据的字节数。

这是编写RegSetValueEx的正确方法,这样字符开关集就可以工作:

DWORD cch=0;
StrCchLength(ext_id,1024,&cch);
RegSetValueEx(hk, TEXT("ext_id"), 0, REG_SZ, (const BYTE *)ext_id, ( cch + 1) * sizeof(TCHAR));

请注意,我使用了StrSafe.h中的StrCchLength API而不是strlen,wcslen,lstrlen或相关API。 StrCchLength和相关API具有帮助您编写更安全代码的功能 - 在这种情况下,而不是对注册表执行无限制写入,ext_id被“剪切”为1024个字符。

注意:你需要在这里非常小心。一些Registry API被记录为要求字节计数为EXCLUDE终止零,RegSetValueEx要求字节计数包括零终止符。所以我在字符串THEN的字符数上加上+1乘以TCHAR的大小来得到类型的数量。


在读取值时 - 需要查询两次的原因是RegQueryValueEx使用lpcbData指针有两个目的 - 作为输入值指定缓冲区的大小,并作为输出值,返回写入的实际字节数到缓冲区(成功时)或者,如果返回代码是ERROR_MORE_DATA,则不写入缓冲区,但* lpcbData被设置为所需的字节数。

TCHAR ext_id[20];
DWORD extIdLength = sizeof (ext_id); // you need to initialize this
LONG err = RegQueryValueEx(hk, TEXT("ext_id"), NULL, NULL, (LPBYTE)ext_id, &extIdLength) ;
if(err == ERROR_MORE_DATA) {
  // you can try again here, using extIdLength to create a new buffer that IS big enough
}
if(err == ERROR_SUCCESS){
  ...
相关问题