windows 注册表编程

来源:互联网 发布:英雄无敌 知乎 编辑:程序博客网 时间:2024/06/06 15:37

注册表是windows操作系统中用来存储系统设置的数据库。里面存储一些例如系统语言、已安装软件的配置、系统硬件配置等信息。用户可以通过对注册表的增减、修改等操作使得系统达到自己所需的运行效果。windows提供了一个注册表编辑器工具用来查看和修改注册表。除此之外,还提供了.reg为后缀的注册表文件对注册表写入数据。但是在我们编写应用程序相应修改注册表时,这些方法都比较麻烦,最直接的方法就是采用windows开放出的API函数对其进行修改。


1、注册表结构

为了方便管理,注册表被设计成一个树状结构,根键位于树状结构的最顶层,不同的windows版本其根键可能略有不同。下面是常用的六大根键:
(1)HKEY_CLASSES_ROOT
定义了系统中所有的文件类型标识和基本操作标识。
(2)HKEY_CURRENT_USER
包含当前用户的配置文件,包括环境变量、桌面设置、网络连接、打印机和程序首选项等信息。
(3)HKEY_LOCAL_MACHINE
包含于本地计算机系统相关的信息,包括硬件和操作系统数据,如总线类型、系统内存、设备驱动程序和启动控制数据等信息。
(4)HKEY_USERS
定义了所有用户的信息,这些信息包括动态加载的用户配置文件和默认的配置文件。
(5)HKEY_CURRENT_CONFIG
包含计算机在启动时由本地计算机系统使用的硬件配置文件的相关信息。该信息用于配置某些装置,如要加载的应用程序和显示时要使用的背景颜色等。
(6)HKEY_DTN_DATA
包括了系统的动态信息,如即插即用的硬件信息。

每个根键下面又可以有多个注册表项,每个注册表项下又可以有多个子项和值项。但不管怎样,每个注册表项总有一个默认的值项。每个值项有名称、数据类型和数据值三部分。注册表值项常用的数据类型如下:
值项类型                                            数据类型                          功能
REG_BINARY                                     二进制                         二进制数据
REG_DWORD                                    四字节                         四字节数值数据
REG_DWORD_BIG_ENDIAN               四字节                         四字节数值数据(注1)
REG_DWORD_LITTLE_ENDIAN           四字节                         四字节数值数据(注2)
REG_LINK                                         字符串                         文件路径
REG_NONE                                      未知                             用于无须分类的数据
REG_SZ                                            字符串                         文本字符串
REG_EXPAND_SZ                             字符串                          带变量的文本字符串
REG_MULTI_SZ                                多字符串                       以null间隔的字符串集合
REG_RESOURCE_LIST                       字符串                          设备使用的资源列表
注1:BIG_ENDIAN——数据在内存中存储时,数据的最高字节存放在地址最低位,最低字节存放在地址最高位,依次排列。
注2:LITTLE_ENDIAN——与上面相反,数据的最高字节存放在地址最高位,最低字节存放在地址最低位,依次排列。
(这是一个字节序的问题,代表着两大CPU派系,motorola和IBM的Power PC采用的是BIG_ENDIAN的字节序,而Intel的X86架构采用的是LITTLE_ENDIAN。C++编写程序时数据存储顺序跟编译器所在的CPU平台无关,但是JAVA则是指定BIG_ENDIAN的字节序,而且所有的网络协议也是采用BIG_ENDIAN的字节序来传输数据的。这样,当你的程序要与其他不同平台下的程序交互时就必须注意字节序的问题。就目前来看,LITTLE_ENDIAN占有一定的优势,因为采用LITTLE_ENDIAN的字节序时,在进行数据类型转换时,特别是指针类型,不需要考虑地址问题。但是BIG_ENDIAN更符合人类的思维习惯。)


2、注册表操作
windows定义了一系列操作注册表的API函数,但是这些API函数需要设置的参数很多。为此,MFC对Win32的API函数进行封装,提供了一个简单方便的类CRegKey。除此之外,windows系统还提供了操作注册表的组件接口函数。

(1)CRegKey类的操作方法
LONG Create( HKEY hKeyParent, LPCTSTR lpszKeyName, LPTSTR lpszClass = REG_NONE, DWORD dwOptions = REG_OPTION_NON_VOLATILE, REGSAM samDesired = KEY_ALL_ACCESS, LPSECURITY_ATTRIBUTES lpSecAttr = NULL, LPDWORD lpdwDisposition = NULL );
该成员函数新建注册表项,如果该注册表已存在,则打开。如果函数执行成功返回ERROR_SUCCESS(#define ERROR_SUCCESS 0L)。函数参数介绍如下:
hKeyParent                        // 注册表根键
lpszKeyName                     // 新建或要打开的注册表项名称
lpszClass                            // 欲创建的注册表项的类型,默认为REG_NONE
dwOptions                         // 操作的选项,具体参照API函数RegCreateKeyEx
samDesired                        // 定义访问权限,默认值为KEY_ALL_ACCESS
lpSecAttr                            // 定义安全性,默认值为NULL
lpdwDisposition                 // 返回新建后打开的注册表项的状态,参照RegCreateKeyEx
除此之外CRegKey的操作方法还有:(具体的参数可查阅MSDN)
LONG Open( HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired = KEY_ALL_ACCESS );
打开注册表项,如果函数执行成功返回ERROR_SUCCESS。
LONG SetValue( DWORD dwValue, LPCTSTR lpszValueName );
LONG SetValue( LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL );
LONG SetValue( HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL );
设置注册表值项的值,如果函数执行成功返回ERROR_SUCCESS。
LONG QueryValue( DWORD& dwValue, LPCTSTR lpszValueName );
LONG QueryValue( LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount );
查询注册表值项数据,如果函数执行成功返回ERROR_SUCCESS。
void Attach( HKEY hKey );
将指定的注册表项与该类绑定。
HKEY Detach( );
与Attach配套使用,解除该类与注册表项的绑定。
LONG SetKeyValue( LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL );
设置注册表项的值项的值,该注册表项必须是该类所绑定的注册表项的子项,如果函数执行成功返回ERROR_SUCCESS。
LONG DeleteSubKey( LPCTSTR lpszSubKey );
删除指定的注册表项,该注册表项必须是该类所绑定的注册表项的子项,如果函数执行成功返回ERROR_SUCCESS。
LONG DeleteValue( LPCTSTR lpszValue );
删除该类所绑定的注册表项的值项,如果函数执行成功返回ERROR_SUCCESS。
LONG RecurseDeleteKey( LPCTSTR lpszKey );
删除指定的注册表项,该注册表项必须是该类所绑定的注册表项的子项,如果函数执行成功返回ERROR_SUCCESS。
LONG Close( );
释放掉该类所绑定的注册表项的句柄,如果函数执行成功返回ERROR_SUCCESS。
(注意:在windows NT下,DeleteSubKey函数只能删除没有子项的注册表项,RecurseDeleteKey函数则不管该注册表项有无子项,都能删除。而在windows 95下,DeleteSubKey函数则不管该注册表项有无子项,都能删除。)

(2)Win32 API函数
以下windows提供的一些常用的用于操作注册表的API函数,还有其他的一些API可查阅MSDN。
LONG RegCreateKey(
HKEY hKey,        // 根键
LPCTSTR lpSubKey, // 欲创建的注册表项的名称
PHKEY phkResult   // 返回打开的注册表项,类型是HKEY的指针
);
该函数打开指定的注册表项或子项,如果该项不存在,则新建一个注册表项或子项。如果函数执行成功返回ERROR_SUCCESS。
LONG RegCreateKeyEx(
HKEY hKey,                // 根键
LPCTSTR lpSubKey,         // 欲创建的注册表项的名称
DWORD Reserved,           // 系统保留
LPTSTR lpClass,           // 欲创建的注册表项的类型
DWORD dwOptions,          // 操作参数,可选有:REG_OPTION_NON_VOLATILE,REG_OPTION_VOLATILE,REG_OPTION_BACKUP_RESTORE (具体设置查阅MSDN)
REGSAM samDesired,        // 设置访问权限
LPSECURITY_ATTRIBUTES lpSecurityAttributes,         // 定义安全性
PHKEY phkResult,          // 返回指向打开的注册表项的指针
LPDWORD lpdwDisposition   // 返回该注册表项的状态,可选有:REG_CREATED_NEW_KEY(新建),REG_OPENED_EXISTING_KEY(已存在)
);
该函数的功能与RegCreateKey大致相同,只不过提供更全面的设置参数。其中注册表的访问权限可有以下几种选择:
访问权限                                                描述
KEY_ALL_ACCESS                               允许所有访问权限
KEY_CREATE_LINK                             允许创建注册表项的链接
KEY_CREATE_SUB_KEY                       允许创建子项
KEY_ENUMERATE_SUB_KEYS             允许枚举注册表项的子项
KEY_EXECUTE                                   允许读操作
KEY_NOTIFY                                     允许注册表项的修改通知
KEY_QUERY_VALUE                          允许查询值项
KEY_READ                                        允许枚举子项、修改通知和查询值项
KEY_SET_VALUE                               允许设置注册表项的值项
KEY_WRITE                                      允许创建子项和设置值项

LONG RegOpenKey(
HKEY hKey,        // 根键
LPCTSTR lpSubKey, // 欲打开的子项名称
PHKEY phkResult   // 返回指向打开的子项的指针
);
LONG RegOpenKeyEx(
HKEY hKey,         // 根键
LPCTSTR lpSubKey, // 欲打开的子项名称
DWORD ulOptions,   // 系统保留
REGSAM samDesired, // 设置访问权限
PHKEY phkResult    // 返回指向打开的子项的指针
);
用于打开注册表中指定的项或子项。如果函数执行成功返回ERROR_SUCCESS。

LONG RegSetValue(
HKEY hKey,         // 已打开的注册表项
LPCTSTR lpSubKey, // 子项的名称
DWORD dwType,      // 值项的类型
LPCTSTR lpData,    // 存储欲写入数据的指针
DWORD cbData       // 欲写入数据的大小
);
用于设置注册表项中默认值项的数据。如果函数执行成功返回ERROR_SUCCESS。
(注意:由于是设置默认值项的数据,故值项类型参数一项只能设定为REG_SZ)
LONG RegSetValueEx(
HKEY hKey,           // 已打开的注册表项
LPCTSTR lpValueName, // 欲写入数据的值项名称
DWORD Reserved,      // 系统保留
DWORD dwType,        // 值项的类型
CONST BYTE *lpData, // 存储欲写入数据的指针
DWORD cbData         // 欲写入数据的大小
);
用于设置注册表项中指定值项的数据。如果函数执行成功返回ERROR_SUCCESS。

LONG RegDeleteKey(
HKEY hKey,         // 欲操作的注册表项
LPCTSTR lpSubKey   // 欲删除的子项名称
);
用于删除注册表中的指定项或子项。如果函数执行成功返回ERROR_SUCCESS。
LONG RegDeleteValue(
HKEY hKey,            // 已打开的注册表项
LPCTSTR lpValueName   // 欲删除的值项名称
);
用于删除注册表中的指定值项。如果函数执行成功返回ERROR_SUCCESS。

LONG RegQueryValue(
HKEY hKey,       // 已打开的注册表项
LPCTSTR lpSubKey,     // 子项的名称
LPTSTR lpValue, // 返回值项的数据
PLONG lpcbValue // 返回值项数据的空间大小(在内存中所占的字节数)
);
用于查询注册表项中默认值项的值。如果函数执行成功返回ERROR_SUCCESS。
LONG RegQueryValueEx(
HKEY hKey,           // 已打开的注册表项
LPTSTR lpValueName, // 欲查询的值项的名称
LPDWORD lpReserved, // 系统保留
LPDWORD lpType,      // 返回值项的类型
LPBYTE lpData,       // 返回值项的数据
LPDWORD lpcbData     // 返回值项数据的空间大小(在内存中所占的字节数)
);
用于查询指定注册表项的指定值项的数据。如果函数执行成功返回ERROR_SUCCESS。

LONG RegEnumKey(
HKEY hKey,     // 欲查询的注册表项
DWORD dwIndex, // 指定子项的索引
LPTSTR lpName, // 返回子项的名称
DWORD cbName   // 指定存储子项名称返回值空间的大小
);
用于枚举指定注册表项中子项。如果函数执行成功返回ERROR_SUCCESS。
LONG RegEnumKeyEx(
HKEY hKey,          // 欲查询的注册表项
DWORD dwIndex,      // 指定子项的索引
LPTSTR lpName,      // 返回子项的名称
LPDWORD lpcbName,   // 指定存储子项名称的空间的大小
LPDWORD lpReserved, // 系统保留
LPTSTR lpClass,     // 返回子项的类型
LPDWORD lpcbClass, // 指定存储子项类型的空间的大小
PFILETIME lpftLastWriteTime      // 返回子项的最后修改时间
);
用于枚举指定注册表项的子项。如果函数执行成功返回ERROR_SUCCESS。
LONG RegEnumValue(
HKEY hKey,              // 欲查询的注册表项
DWORD dwIndex,          // 指定值项的索引
LPTSTR lpValueName,     // 返回值项的名称
LPDWORD lpcbValueName, // 返回值项名称的空间大小(在内存中所占的字节数)
LPDWORD lpReserved,     // 系统保留
LPDWORD lpType,         // 返回值项的类型
LPBYTE lpData,          // 返回值项的数据
LPDWORD lpcbData        // 返回值项数据的空间大小(在内存中所占的字节数)
);
用于枚举指定注册表项中的值项。如果函数执行成功返回ERROR_SUCCESS。
(注意:MSDN文档说明32位的应用程序都应该使用RegEnumKeyEx函数来查询注册表项的子项,另外,在使用该函数时,lpcbName、lpcbClass、lpcbValueName和lpcbData所指向的空间以及cbName必须在初始化时设定足够的大小,保证其初始化值比返回值要大,否则将产生不可预知的错误,无法得到预期的结果。在枚举过程中,可通过"!=ERROR_NO_MORE_ITEMS"或“==ERROR_SUCCESS"来判断枚举是否接受。)

LONG RegCloseKey(
HKEY hKey   // 欲关闭的子项
);
用于关闭注册表项,并释放该注册表项的句柄。如果函数执行成功返回ERROR_SUCCESS。

(3)组件函数
除了CRegKey类和Win32 API函数,windows还提供了两个组件函数:SHEnumKeyEx和SHEnumValue。前者可以枚举注册表项用法和RegEnumKeyEx相同,后者可以枚举注册表值项,用法和RegEnumValue相同。
注意:该组件函数是存放在一个静态链接库中,所以必须在使用该函数的源文件的初始部分添加以下代码:
#include "SHLWAPI.H"
#pragma comment(lib, "SHLWAPI")

来自: http://hi.baidu.com/halty86/blog/item/1790325984cf918b800a18eb.html
原创粉丝点击