注册表的组织方式跟文件目录比较相似,主要分为根键、子键和键值项三部分,
1.1 根键
分为5个,分别为:
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIG
1.2 子键
可以有多个子键和键值项,就像一个目录中可以有多个子目录和多个文件一样。
1.3 键值项
可以理解为文件,由三部分组成,分别为:名称、类型、数据。
类型分为:
REG_BINARY 二进制数据
REG_DWORD 32位双字节数据
REG_SZ 以0节尾的字符串
REG_DWORD_BIG_ENDIAN 高位排在低位的双字
REG_EXPAND_SZ 扩展字符串,可以加入变量 如%PATH%
REG_LINK UNICODE符号链接
REG_RESOURCE_LIST 设备驱动程序资源列表
REG_MULTI_SZ 多字符串
对注册表操作前应该先打开指定的键,然后通过键的句柄进行操作。
需要注意的是打开键的句柄后需要关闭(RegCloseKey())。
打开键句柄 RegOpenKeyEx()
函数原型:
RegOpenKeyEx(
hKey, // 父键句柄
lpSubKey, // 子键句柄
dwOptions, // 系统保留,指定为0
samDesired, // 打开权限
phkResult // 返回打开句柄
);
打开权限有多种,可以指定为KEY_ALL_ACCESS(包含所有权限);函数执行成功返回ERROR_SUCCESS。
KEY_CREATE_LINK 许可创建一个符号链接
KEY_CREATE_SUB_KEY 创建子键
KEY_ENUMERATE_SUB_KEYS 列举子键
KEY_EXECUTE 访问
KEY_NOTIFY 提供更改通知
KEY_QUERY_VALUE 查询子键数据
KEY_ALL_ACCESS 联合了KEY_QUERY_VALUE、KEY_SET_VALUE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFY、KEY_CREATE_SUB_KEY、KEY_CREATE_LINK访问权限并且加上所有的标准访问权限,除了SYNCHRONIZE
KEY_READ 联合了STANDARD_RIGHIS_READ、KEY_QUERY_VALUE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFY访问权限
KEY_WOW64_64KEY Windows XP:使64位或者342位应用程序打开64位键
KEY_WOW64_32KEY Windows XP:使64位或者342位应用程序打开32位键
KEY_WRITE 联合STANDARS_RIGHTS_WRITE、KEY_SET_VALUE、KEY_CREATE_SUB_KEY访问权限
常用到的子键/键值的信息如:子键/键值的数量,长度,以及数据的最大长度等,可以通过函数RegQueryInfoKey()获取。
函数原型:
RegQueryInfoKey(
hKey, // 要获取信息的句柄
lpClass, // 接收创建键时的Class字符串
lpcbClass, // lpClass的长度
lpReserved, // 系统保留,指定为0
lpcSubkeys, // 子键数量
lpcbMaxSubKeyLen, // 子键中最长名称的长度
lpcbMaxClassLen, // 子键中最长Class字符串长度
lpValues, // 键值数量
lpcbMaxValueNameLen, // 键值项中最长名称的长度
lpcbMaxValueLen, // 键值项数据最大长度
lpcbSecurityDescriptor, // 安全描述符长度
lpftLastWriteTime // FILETIME结构,最后修改时间
);
实际使用时只需要填写自己需要的即可;返回的长度不包括结尾的0字符,在使用时应该用长度+1。
3.1 获取一个项的值
使用函数RegQueryValueEx()函数获取一个项的设置值,函数原型:
LONG RegQueryValueEx(
HKEY hKey, // 一个已经打开项的句柄,或者指定一个标准项名
LPCTSTR lpValueName, // 要获取值的名字
LPDWORD lpReserved, // 保留字,设置为0
LPDWORD lpType, // 用于装载取回数据类型的一个变量
LPBYTE lpData, // 用于装载指定值的一个缓冲区
LPDWORD lpcbData // 用于装载lpData缓冲区长度的一个变量。一旦返回,它会设为实际装载到缓冲区的字节数
);
返回值:0=成功,其它表示失败
lpValueName指向要查询值的名字的字符串(以空字符结束),如果设置为NULL,那么这个函数找这个键的未命名或默认值的类型和数据。
lpReserved必须设置为NULL。
4. 枚举子键信息
枚举子键信息可以用函数RegEnumKeyEx()实现,调用该函数返回子键的名称、长度和一些相关数据。直到返回ERROR_NO_MORE_ITEMS说明已经枚举完所有的数据。函数原型:
RegEnumKeyEx(
hKey, // 被枚举的键句柄
dwIndex, // 子键索引编号
lpName, // 子键名称
lpcbName, // 子键名称长度
lpReserved, // 系统保留,指定为0
lpClass, // 子键类名
lpcbClass, // 子键类名长度
lpftLastWriteTime // 最后写入时间
);
使用RegEnumValue()函数枚举键值信息,函数原型
RegEnumValue(
hKey, // 被枚举的键句柄
dwIndex, // 子键索引编号
lpValueName, // 键值名称
lpcbValueName, // 键值名称长度
lpReserved, // 系统保留,指定为0
lpType, // 键值数据类型
lpData, // 键值数据
lpcbData // 键值数据长度
);
6.1 创建子键
创建子键与打开子键类似,可以使用RegCreateKeyEx()函数实现。函数原型:
RegCreateEx(
hKey, // 父键句柄
lpSubKey, // 子键句柄
Reserved, // 系统保留,指定为0
lpClass, // 定义子键类名,通常为NULL
dwOptions, // 创建子键时的选项
samDesired, // 创建后操作权限
lpSecurityAttributes, // 指向SECURITY_ATTRIBUTES结构,指定键句柄的继承性
phkResult, // 返回创建句柄
lpdwDisposition, // 通常设为NULL
);
也可以用16位下的函数RegCreateKey()实现
6.2 删除一个子键
删除一个键使用函数RegDeleteKey(),函数原型:
RegDeleteKey(
hKey, // 主键句柄
lpSubKey // 子键名称字符串
);
7.1 创建键值可以用RegSetValueEx()函数实现,函数原型:
RegSetValueEx(
hKey, // 键句柄,键值项将保存在此键下
lpValueName, // 键值项名称
Reserved, // 系统保留,指定为0
dwType, // 键值项类型
lpData, // 键值项数据
cbData, // 键值项长度
);
使用时需要注意,参数lpData和cbData的值要根据dwType的值来设定。按照常用的设置分三种情况:
1. dwType为REG_SZ时,lpData为要设置的数据,cbData为数据的长度。
2. dwType为REG_DWORD时,cbData必须设置为4。
3. dwType为REG_BINARY时,cbData也必须设置为4。
调用时,如果键值项名称已经存在,会覆盖原有键值项,如果没有,就新建一个。
7.2 删除键值项
删除键值项可以用RegDeleteValue()函数,函数原型:
RegDeleteValue(
hKey, // 父键句柄
lpValueName, // 要删除的键值项名称
);
8. 备份/恢复注册表
8.1 备份注册表
备份注册表可以用RegSaveKey()函数实现,函数原型:
RegSaveKey(
hKey, // 要备份的键句柄
lpFile, // 保存信息的文件名称
lpSecurityAttributes // 文件安全属性
);
函数参数:
hKey:要备份的键句柄,可以是系统预定义的,也可以是RegOpenKey()打开或RegCreateKeyEx()创建的;
lpFile:保存信息的文件名称,这个文件必须是不存在的,这个文件也不能有扩展名;
lpSecurityAttributes:在NT系统中用来设置新文件的安全属性,通常设置为NULL。
使用该函数时需要有SE_BACKUP_NAME权限,这个权限不能在RegOpenKey()或RegCreateKeyEx()指定,需要提升程序的权限。
7.2 恢复注册表可以用RegRestoreKey()函数实现
函数原型:
RegStoreKey(
hKey, // 要恢复的键句柄
lpFile, // 保存信息的文件名称
dwFlag // 标志是否易失 为TRUE,暂时恢复注册表,为FALSE永久修改注册表值
);
同样需要注意的是使用该函数需要有SE_RESTORE_NAME权限。
参考链接:C++ 注册表编程 - 程序员大叔 - 博客园