2010-08-05 99 views
0

所以我一直停留在这一段时间......还以为我得到它的工作,但它有时会中断,我不知道确切的原因...C++读取和写入注册表正确

我不知道这是否重要,但我正在编写这个内部浏览器帮助对象(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 64bit。

测试了32位Windows 7 ...

问题一起在Windows XP的IE 6来了,也没有工作,但似乎如果我再打电话函数RegQueryValueEx,它会返回正确的值,所以我注意到下一个请求...

我还注意到,根据我发送到服务器的其他字符串,它会工作不同,这可能是由于我相对较新的C++ ,(只有几个星期真的在),我确信我正在做一些真正错误的事情。

呵呵我在msdn上读到我需要在打开注册表项的标志中使用KEY_WOW64_32KEY或KEY_WOW64_64KEY,这取决于情况......但这对我来说确实非常必要(浏览器6.0到8.0的BHO)

回答

0

你已经失去了Windows处理unicode的方式。 Dev Studio有一个方便的开关,可以让您在应用程序的Unicode和Multibyte版本之间切换,并且您正在为Unicode编译。

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

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

TCHAR是一个宏,意思是wchar_t当为构建多字节字符集应用程序构建Unicode和`char1时。

_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而不是strlen的使用StrCchLength API,wcslen,lstrlen或相关的API。 StrCchLength和相关API具有帮助您编写更安全的代码的功能 - 在这种情况下,而不是执行无限注写入注册表,ext_id被“剪辑”为1024个字符。

注意:您在这里需要非常小心。某些注册表API被记录为要求字节数EXCLUDE终止零,RegSetValueEx要求字节数包含零终止符。所以我给字符串的字符数加上+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){ 
    ... 
+0

thanx的快速答复.... 是否写入注册表有从中读什么影响吗?我理解你所提出的所有观点,但是我在Windows XP中从注册表中读取问题似乎是唯一的解决方法,就是在必要时打开并查询密钥两次,以使其正常工作 最奇怪的是,当我在同一个函数中使用了AtlEscapeUrl,而RegQueryValueEx在WindowsXP中失败了,但是在Windows7下工作,当我将这个函数移出到子函数时,它又开始工作了......这是怎么回事? – user385342 2010-08-05 10:42:25