windows 注册表操作注意点
2014-05-06 12:17
239 查看
最近使用到RegQueryValueEx这个函数,发现了两个小问题,总是解决不了,上网上找资料发现不是找不到就是找的不对,现在终于解决了,所以分享给大家来看看,给那些还在困惑中徘徊的和我一样的菜鸟看看,大牛就就直接飘过吧。
RegQueryValueEx这个函数MSDN是这样解释的
This function retrieves the type and data for a specified value name associated with an open registry key. 获取一个项的设置值
LONG RegQueryValueEx(
HKEY hKey,
LPCWSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
第一个参数hKey是一个已打开项的句柄,或者指定一个标准项名。
第二个参数lpValueName是要获取值的名字。
第三个参数lpReserved未用,设为零。
第四个参数lpType用于装载取回数据类型的一个变量。
第五个参数lpData用于装载指定值的一个缓冲区。
第六个参数lpcbData用于装载lpData缓冲区长度的一个变量。一旦返回,它会设为实际装载到缓冲区的字节数。
这个都是很常规的事情,下面我们来看看今天我要说的两个关于这个函数极小的细节,也许会给你们编程带来一定的困难。
第一,无法获取长的键值名
这里其实键值名的长度是有限制的应该是255吧,但是我发现我在使用这个函数的时候在规定的长度内,比如我写一个250的长度的键值名AAAAAAAAAAAAA……,这个函数就调用失败了,代码如下:
这是为什么呢?现在我来告诉你们,RegQueryValueEx在获取键内容的时候,首先需要获取键长度,否则以上一次获取的长度为准,也就是说要么你这样写:
要么你就在每次调用
RegQueryValueEx(hKey,achValue,NULL,&cType,(LPBYTE)ValueInfo,&ValueSize)==ERROR_SUCCESS函数之前写上ValueSize=MAX_VALUE_NAME,这个在之前的宏定义中有,是2048。
这样就可以读出长文件名了。
这个问题很可能是因为您调用了RegQueryValueEx之后,没有恢复接收数据的缓冲区的大小所导致的。RegQueryValueEx函数的原型如下:
其中最后一个参数是输入输出型的,输入时表示接受数据的缓冲区的大小,当该函数返回时,该值包含了复制到缓冲区的数据的大小。而当缓冲区的大小不能容纳要获取的数据时,该函数返回ERROR_MORE_DATA并在lpcbData中存放了实际需要的缓冲区的大小(字节数)。
建议您在每次调用之前恢复原先的缓冲区的大小,问题应该就解决了。
例如:
::RegQueryValueEx(hkey,"MaterialQuery",NULL,&dwValueType,szMaterialQuery,
&dwValueLen);
dwValueLen = 80;
::RegQueryValueEx(hkey,"ApprovePerson",NULL,&dwValueType,szApprovePerson,
&dwValueLen);
dwValueLen = 80;
::RegQueryValueEx(hkey,"ContractID",NULL,&dwValueType,szContractID,
&dwValueLen);
第二,如何读出REG_DWORD值
关于这条我也在网上找了好久,都没有什么结果,有人说用一个union结构体来解决,但是没有说具体怎么解决,如果直接用printf(“%d”,(DWORD)ValueInfo);来强制转换的话,我们会发现虽然不报错,但是数值并不对。最终这个问题是这样解决的,正如上面的代码:
RegQueryValueEx这个函数MSDN是这样解释的
This function retrieves the type and data for a specified value name associated with an open registry key. 获取一个项的设置值
LONG RegQueryValueEx(
HKEY hKey,
LPCWSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
第一个参数hKey是一个已打开项的句柄,或者指定一个标准项名。
第二个参数lpValueName是要获取值的名字。
第三个参数lpReserved未用,设为零。
第四个参数lpType用于装载取回数据类型的一个变量。
第五个参数lpData用于装载指定值的一个缓冲区。
第六个参数lpcbData用于装载lpData缓冲区长度的一个变量。一旦返回,它会设为实际装载到缓冲区的字节数。
这个都是很常规的事情,下面我们来看看今天我要说的两个关于这个函数极小的细节,也许会给你们编程带来一定的困难。
第一,无法获取长的键值名
这里其实键值名的长度是有限制的应该是255吧,但是我发现我在使用这个函数的时候在规定的长度内,比如我写一个250的长度的键值名AAAAAAAAAAAAA……,这个函数就调用失败了,代码如下:
#define MAX_KEY_LENGTH 1024 #define MAX_VALUE_NAME 2048 TCHAR achClass[MAX_PATH]={0}; DWORD cchClassName = MAX_PATH; DWORD cSubKeys=0; DWORD cbMaxSubKey; DWORD cchMaxClass; DWORD cValues; DWORD cType; DWORD cchMaxValue; DWORD cbMaxValueData; DWORD cbSecurityDescriptor; FILETIME ftLastWriteTime; DWORD i, retCode; TCHAR achValue[MAX_VALUE_NAME]; TCHAR ValueInfo[MAX_VALUE_NAME]; DWORD ValueSize=MAX_VALUE_NAME; DWORD cchValue=MAX_VALUE_NAME; retCode = RegQueryInfoKey(hKey,achClass,&cchClassName,NULL,&cSubKeys,&cbMaxSubKey, &cchMaxClass,&cValues,&cchMaxValue,&cbMaxValueData, &cbSecurityDescriptor,&ftLastWriteTime); if (cValues) { printf( "/nNumber of values: %d/n", cValues); for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) { achValue[0] = '/0'; retCode = RegEnumValue(hKey,i,achValue,&cchValue,NULL,NULL,NULL,NULL); if (retCode == ERROR_SUCCESS ) { printf("(%d) %s/n",i+1,achValue); } ValueSize=MAX_VALUE_NAME; if(RegQueryValueEx(hKey,achValue,NULL,&cType,(LPBYTE)ValueInfo,&ValueSize)==ERROR_SUCCESS) { if(cType==REG_EXPAND_SZ||cType==REG_SZ||cType==REG_MULTI_SZ) { printf("%s/n",ValueInfo); } else if(cType==REG_DWORD||cType==REG_BINARY) { printf("%d/n",(long)*(short *)ValueInfo); } } } }
这是为什么呢?现在我来告诉你们,RegQueryValueEx在获取键内容的时候,首先需要获取键长度,否则以上一次获取的长度为准,也就是说要么你这样写:
RegQueryValueEx(hKey,achValue,NULL,NULL,NULL,&ValueSize)==ERROR_SUCCESS; RegQueryValueEx(hKey,achValue,NULL,&cType,(LPBYTE)ValueInfo,&ValueSize)==ERROR_SUCCESS;
要么你就在每次调用
RegQueryValueEx(hKey,achValue,NULL,&cType,(LPBYTE)ValueInfo,&ValueSize)==ERROR_SUCCESS函数之前写上ValueSize=MAX_VALUE_NAME,这个在之前的宏定义中有,是2048。
这样就可以读出长文件名了。
这个问题很可能是因为您调用了RegQueryValueEx之后,没有恢复接收数据的缓冲区的大小所导致的。RegQueryValueEx函数的原型如下:
其中最后一个参数是输入输出型的,输入时表示接受数据的缓冲区的大小,当该函数返回时,该值包含了复制到缓冲区的数据的大小。而当缓冲区的大小不能容纳要获取的数据时,该函数返回ERROR_MORE_DATA并在lpcbData中存放了实际需要的缓冲区的大小(字节数)。
建议您在每次调用之前恢复原先的缓冲区的大小,问题应该就解决了。
例如:
::RegQueryValueEx(hkey,"MaterialQuery",NULL,&dwValueType,szMaterialQuery,
&dwValueLen);
dwValueLen = 80;
::RegQueryValueEx(hkey,"ApprovePerson",NULL,&dwValueType,szApprovePerson,
&dwValueLen);
dwValueLen = 80;
::RegQueryValueEx(hkey,"ContractID",NULL,&dwValueType,szContractID,
&dwValueLen);
第二,如何读出REG_DWORD值
关于这条我也在网上找了好久,都没有什么结果,有人说用一个union结构体来解决,但是没有说具体怎么解决,如果直接用printf(“%d”,(DWORD)ValueInfo);来强制转换的话,我们会发现虽然不报错,但是数值并不对。最终这个问题是这样解决的,正如上面的代码:
else if(cType==REG_DWORD||cType==REG_BINARY) { printf("%d/n",(long)*(short *)ValueInfo); }
相关文章推荐
- java操作注册表时,注意路径问题
- Windows Practice_文件_注册表操作
- java如何操作注册表(Preferences类)(在windows的注册表中保存、读取)
- WINDOWS下操作注册表 REG_EXPAND_SZ与REG_SZ的区别
- 用Java操作Windows注册表
- Windows驱动编程 文件读写 以及注册表操作
- Windows内核函数(3) - 内核模式下的注册表操作
- windows搜索时提示“意外错误 操作无法完成”的解决方法(利用注册表)
- 64位系统下操作注册表的注意事项
- 使用Java操作Windows注册表
- 64bit系统下操作注册表的注意事项
- windows中对环境变量操作实质上是对注册表的操作
- Windows 开发之注册表操作-UAC
- Tip - 注意:32位程序访问64位系统上的Windows注册表
- Windows注册表操作基础代码
- windows中对环境变量操作实质上是对注册表的操作
- goLang 操作windows注册表
- 需注意Windows误操作易造成硬盘故障 www.dl8848.com
- Windows Phone FMラジオを操作するアプリの注意点
- python操作windows注册表