C++接触了一段时间,最近在捣鼓PatrolBot移动机器人小车,在看源码的时候发现有对注册表操作的代码,第一次接触,便来此记录一番。
首先把用到注册表操作的这个函数(ArUtil类的成员函数)搬上来,该函数功能是从注册表中获取一个字符串。
AREXPORT bool ArUtil::getStringFromRegistry(REGKEY root,
const char *key,
const char *value,
char *str,
int len)
{
#ifndef WIN32
return false;
#else // WIN32
HKEY hkey;
int err;
unsigned long numKeys;
unsigned long longestKey;
unsigned long numValues;
unsigned long longestValue;
unsigned long longestDataLength;
char *valueName;
unsigned long valueLength;
unsigned long type;
char *data;
unsigned long dataLength;
HKEY rootKey;
switch (root)
{
case REGKEY_CLASSES_ROOT:
rootKey = HKEY_CLASSES_ROOT;
break;
case REGKEY_CURRENT_CONFIG:
rootKey = HKEY_CURRENT_CONFIG;
break;
case REGKEY_CURRENT_USER:
rootKey = HKEY_CURRENT_USER;
break;
case REGKEY_LOCAL_MACHINE:
rootKey = HKEY_LOCAL_MACHINE;
break;
case REGKEY_USERS:
rootKey=HKEY_USERS;
break;
default:
ArLog::log(ArLog::Terse,
"ArUtil::getStringFromRegistry: Bad root key given.");
return false;
}
/// 打开一个指定的注册表键
if ((err = RegOpenKeyEx(rootKey, key, 0, KEY_READ, &hkey)) == ERROR_SUCCESS)
{
//printf("Got a key\n");
if (RegQueryInfoKey(hkey, NULL, NULL, NULL, &numKeys, &longestKey, NULL,
&numValues, &longestValue, &longestDataLength, NULL, NULL) == ERROR_SUCCESS)
{
data = new char[longestDataLength+2];
valueName = new char[longestValue+2];
for (unsigned long i = 0; i < numValues; ++i)
{
dataLength = longestDataLength+1;
valueLength = longestValue+1;
if ((err = RegEnumValue(hkey, i, valueName, &valueLength, NULL, //用来枚举指定项的值。
&type, (unsigned char *)data, &dataLength)) == ERROR_SUCCESS)
{
//printf("Enumed value %d, name is %s, value is %s\n", i, valueName, data);
if (strcmp(value, valueName) == 0)
{
if (len < dataLength)
{
ArLog::log(ArLog::Terse,"ArUtil::getStringFromRegistry: str passed in not long enough for data.");
delete data;
delete valueName;
return false;
}
strncpy(str, data, len);
delete data;
delete valueName;
return true;
}
}
}
delete data;
delete valueName;
}
}
return false;
#endif
}
其中,关于注册表操作的函数只要三个:
1. RegOpenKeyEx
2. RegQueryInfoKey
3. RegEnumValue
下面,我们逐一介绍这三个函数。
1. RegOpenKeyEx
WINADVAPI LSTATUS APIENTRY RegOpenKeyEx (HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult);
函数功能:打开一个指定的注册表键
参数hKey:需要打开的主键的名称,HKEY_CLASSES_ROOT / HKEY_CURRENT_CONFIG / HKEY_CURRENT_USER / HKEY_LOCAL_MACHINE / HKEY_USERS,这五个中的一个哦~参数lpSubKey:需要打开的子键的名称
参数ulOptions:保留,设为0
参数samDesired:安全访问标记,也就是权限。主要用到的是KEY_READ。
参数phkResult:输出参数,保存将要打开键的句柄。
返回值:零(ERROR_SUCCESS)表示成功。其他任何值都代表一个错误代码。
举例说明:
看到没有,主键只有这五种情况~
假如我想要主键HKEY_LOCAL_MACHINE下面的Aria子键,那么,
参数hKey要设为HKEY_LOCAL_MACHINE
参数lpSubKey要设为"SOFTWARE\\ActivMedia Robotics\\Aria"
2. RegQueryInfoKey
RegQueryInfoKey(
HKEY hkey, //要获取信息的句柄
LPWSTR lpClass, //接受创建健时的Class字符串
LPDWORD lpcbClass, //lpClass的长度
LPDWORD lpReserved, //系统保留,指定为0
LPDWORD lpcSubKeys, //子键数量
LPDWORD lpcbMaxSubKeyLen, //子键中最长名称的长度
LPDWORD lpcbMaxClassLen, //子键中最长Class字符串长度
LPDWORD lpcVlaues, //键值数量
LPDWORD lpcbMaxValueNameLen, //键值项中最长名称的长度
LPDWORD lpcbMaxValueLen, //键值项数据最大长度
LPDWORD lpcbSecurityDescriptor, //安全描述符长度
FILETIME lpftLastWriteTime, //FILETIME结构,最后修改时间
);
函数功能:获取键的统计信息,查看将要读取的字符串长度是否小于键值数据的最大长度。
参数太多,下面只说明重要的参数吧~
参数hkey:指定要获取信息的键句柄,键的打开方式中必须包括KEY_QUERY_VALUE。
参数lpcSubKeys:指向一个双字,用来返回键中的子键数量。
参数lpcbMaxSubKeyLen:指向一个双字,用来返回所有子键中最长的名称字符串长度,返回的长度不包括字符串结尾的0字符。
参数lpcVlaues:指向一个双字,用来返回键下面的键值项数量。
参数lpcbMaxValueNameLen:指向一个双字,用来返回所有键值项中最长的名称字符串长度,返回的长度不包括字符串结尾的0字符。
参数lpcbMaxValueLen:指向一个双字,用来返回所有键值数据的最大长度。
返回值:零(ERROR_SUCCESS)表示成功。其他任何值都代表一个错误代码。
如一个缓冲区的长度不够,不能容下返回的数据,则函数会返回ERROR_MORE_DATA
例子回头再举吧。。。
3. RegEnumValue
RegEnumValue(
Long hkey, //被枚举的键句柄
Long dwIndex, //子键索引编号
String lpValueName, //键值名称
Long lpcbValueName, //键值名称长度
Long lpReserved, //系统保留,指定为0
Long lpType, //键值数据类型
Byte lpDate, //键值数据
Long lpcbDate //键值数据长度
);