在用VC过程中,会碰到许许多多繁不胜繁的小问题,我想是其中很多都出在C++语言复杂度、API,MFC类库的繁琐,以及函数参数类型的不一致,其它的还有宏,C和C++外部函数的共享,程序的compile,link等等.
今天碰到的二个问题,一个属于函数参数类型的不正确,一个属于链接lib时出现Error的问题.
在用VC过程中,会碰到许许多多繁不胜繁的小问题,我想是其中很多都出在C++语言复杂度、API,MFC类库的繁琐,以及函数参数类型的不一致,其它的还有宏,C和C++外部函数的共享,程序的compile,link等等.
今天碰到的二个问题,一个属于函数参数类型的不正确,一个属于链接lib时出现Error的问题.
一、第一个问题,我想遍历注册表,用API函数RegEnumValue可以实现遍历,但是会出现:有些能遍历,有些却不能遍历,看程序:
这是我第一次写的程序:
1
HKEY regOldHKey;
2
3
//Open Register Key
4
if(::RegOpenKeyEx(HKEY_CURRENT_USER,“Software\\OKI\\CCons33\\UNITTYPE“,0,KEY_ALL_ACCESS,®OldHKey)==ERROR_SUCCESS)
5

{
6
long lResult;
7
DWORD dwIndex;
8
CHAR* tcKeyName = new CHAR[MAX_PATH];
9
DWORD dwKeyNameLen = MAX_PATH;
10
DWORD lpSize,nType;
11
LPBYTE newByte = new BYTE[MAX_PATH]
12
while(TRUE)
13
{
14
//circulate the Register
15
lResult=RegEnumValue(regOldHKey,dwIndex,tcKeyName,&dwKeyNameLen,NULL,NULL,NULL,NULL);
16
if(lResult!=ERROR_SUCCESS)
17
break; //if the End then break;
18
19
//Use the key Get the value
20
if(::RegQueryValueEx(regOldHKey,(LPCTSTR)tcKeyName,NULL,&nType,newByte,&lpSize)==ERROR_MORE_DATA)
21
{
22
newByte=(LPBYTE)“NULL“;
23
}
24
25
//Print the key and the value
26
cout<<“Key:“<<(LPCTSTR)tcKeyName;
27
cout<<“\t“;
28
cout<<“Value:“<<(LPCTSTR)newByte;
29
}
30
}
这个程序有几个问题,根本无法进行遍历!
首先,看看RegEnumValue的函数原型:
LONG RegEnumValue(
HKEY hKey,
DWORD dwIndex,
LPTSTR lpValueName,
LPDWORD lpcValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
MSDN上面提到dwIndex用之前必须要进行初始化,dwIndex在遍历过程中起到了一个计数器的作用,如果不初始化程序编译的时候也会出现警告
所以,第七行应该对dwIndex进行初始化: DWORD dwIndex=0;
第二点,也是我碰到问题才发现的,凡是参数涉及到指针,而实参本身并不是指针类型,需要通过前面加上&地址符来作参数的,如上述的dwKeyNameLen,nType,lpSize等等,API会对其进行变动,一般调用一次没什么问题,但在这里是循环,可能上次写进去的值会影响到下次执行。
就比如拿dwKeyNameLen来说,作字符串缓冲区用。第一次执行是可以的,第一次执行后它的值是lpData字符串的长度。第二次也是可以的,因为第二次遍历lpData的长度小于第一次,但第三次lpData字符串长度比第一次还要长。这时RegEnumValue就会返回一个ERROR_MORE_DATA返回值,并跳出循环。(也就是说,缓冲区的长度满足不了lpData字符串).
与此相关的问题lpSize也是一样,当在RegQueryValueEx函数中,lpSize表示的长度不够时,函数就会拒绝写入newByte.并返回ERROR_MORE_DATA.
So,对于以上问题,我们需要在下一次遍历前再次初始化dwKeyNameLen与newByte的值
dwKeyNameLen=MAX_PATH;
newByte=MAX_PATH;
最后一个问题,dwIndex作为计数器,没有在最后执行自增操作,这样会导致死循环.
正确的代码如下:
1
HKEY regOldHKey;
2
3
//Open Register Key
4
if(::RegOpenKeyEx(HKEY_CURRENT_USER,“Software\\OKI\\CCons33\\UNITTYPE“,0,KEY_ALL_ACCESS,®OldHKey)==ERROR_SUCCESS)
5
{
6
long lResult;
7
DWORD dwIndex=0;
8
CHAR* tcKeyName = new CHAR[MAX_PATH];
9
DWORD dwKeyNameLen = MAX_PATH;
10
LPBYTE newByte = new BYTE[MAX_PATH];
11
DWORD nType;
12
DWORD lpSize=MAX_PATH;
13
LPBYTE pbbinKeyData=NULL;
14
while(TRUE)
15
{
16
//circulate the Register
17
lResult=RegEnumValue(regOldHKey,dwIndex,tcKeyName,&dwKeyNameLen,NULL,NULL,NULL,NULL);
18
if(lResult!=ERROR_SUCCESS)
19
break; //if the End then break;
20
21
//Use the key Get the value
22
long retValue;
23
if((retValue=::RegQueryValueEx(regOldHKey,(LPCTSTR)tcKeyName,NULL,&nType,newByte,&lpSize))==ERROR_MORE_DATA)
24
{
25
newByte=(LPBYTE)“NULL“;
26
}
27
28
//Print the key and the value
29
cout<<“Key:“<<(LPCTSTR)tcKeyName;
30
cout<<“\t“;
31
cout<<“Value:“<<(LPCTSTR)newByte<<endl;
32
dwIndex++;
33
dwKeyNameLen=MAX_PATH;
34
lpSize=MAX_PATH;
35
}
36
}
37
第二个问题:Link时出错问题
在VC中想把注册表删除,查MSDN查到了SHDeleteKey 这个函数,函数使用很简单:
if(SHDeleteKey(HKEY_CURRENT_USER,“Software\\OKI\\CCons32\\NeedDelete“)==ERROR_SUCCESS)

{
cout<<“Delete Finish“<<endl;
}
MSDN上面注明要加入shlwapi.h这个头文件,但我另进去之后,link出现错误. 说是LNK2001无法解析的外部符号“symbol”.
不加,找不到函数定义.
其实解决这个问题很简单.在VC菜单中Project->Setting->Link 下面project options的文本框中,输入shlwapi.lib问题就可以解决了.害得我花了几个小时时间.
(或者,在Code前面加上#pragma comment(lib,”shlwapi.lib”))也可以解决问题。