注册表编程简介
一. 结构简介
注册表实际上是系统中的一个数据库。这个数据库中数据是按“树型”的层次结构来组织的,和Windows中的文件、目录一样。下图就是使用工具Regedit.exe显示的注册表:
图的左面是“树干”,我们称之为“键”;图的右面是“树叶”,我们称之为“键项”。和文件系统一样,键可以包含子键和键项,每个键包含都有一个缺省的键项(默认)。
二. 键的访问
要对目标键的子键或者键项进行操作,必须先获得该键的句柄。
1)打开一个目标键。在一个键句柄下指定子键名来获得目标键。
LONG RegOpenKeyEx(
HKEY hKey, //已经打开键的句柄
LPCTSTR lpSubKey, //需要打开的子键的名称字符串地址
DWORD ulOptions, //保留,必须为0
REGSAM samDesired, // 访问标志
PHKEY phkResult //返回的目标键的句柄
);
在系统中,下面这些预定义的键总是打开的:HKEY_CLASSES_ROOT、HKEY_CURRENT_USER、HKEY_LOCAL_MACHINE、HKEY_USERS。
2)如果需要新增一个键,可以使用下面的函数。
LONG RegCreateKeyEx(
HKEY hKey, //已经打开键的句柄
LPCTSTR lpSubKey, //需要新建的子键的名称字符串地址
DWORD Reserved, //保留
LPTSTR lpClass, // 类字符串地址
DWORD dwOptions, // 特殊选项
REGSAM samDesired, //访问标志
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全选项
PHKEY phkResult, //返回的目标键的句柄
LPDWORD lpdwDisposition // 部署值的缓存。
);
3)当一个打开的键不再需要被使用了,可以将该键关闭,当然预定义键是不需要关闭的J
LONG RegCloseKey(
HKEY hKey //需要关闭的键的句柄
);
4)当一个键下的所有键项都不再需要时,我们可以将这个键删除。
LONG RegDeleteKey(
HKEY hKey, //已经打开键的句柄
LPCTSTR lpSubKey //需要删除键在已打开键下的子键名称地址
);
注意:在Win95时,本函数可以将该键下的所有子键和键项都删除;而在WIN2000/XP时,本函数就只能删除不包含子键的键的所有键项了。
5)当需要遍历一个键下面的所有子键时,可以使用下面的API.
LONG RegEnumKeyEx(
HKEY hKey, //已经打开键的句柄
DWORD dwIndex, //子键索引
LPTSTR lpName, // 子键名称地址
LPDWORD lpcbName, // 子键名称长度的缓存
LPDWORD lpReserved, // 保留
LPTSTR lpClass, // 类地址
LPDWORD lpcbClass, // 类地址缓存
PFILETIME lpftLastWriteTime // 最后写时间
);
三. 键项的访问
要访问某键所包含的键项,必须先要获得键的句柄。一个键项包括“名称”、“类型”和“数据”3项。键项的数据类型常有下面几种:
类型 | 描述 |
REG_BINARY | 二进制原始数据类型 |
REG_DWORD | 一个32位数 |
REG_SZ | 一个结尾为空字符的字符串。可以是Unicode或ANSI字符串,这取决于所用的函数支持哪一个。 |
REG_MULTI_SZ | 一空字符结尾的字符串数组,它将以恋歌字符串结尾。 |
REG_EXPAND_SZ | 以空字符结尾的字符串,其中包括对环境变量的未展开的引号(例如,“%PATH%”)。同样,它是Unicode还是ANSI字符串取决于使用的函数。 |
REG_LINK | Unicode符号链接 |
REG_NONE | 无数据类型的定义 |
1) 新添一个键项并置值,或者给指定键置值。
LONG RegSetValueEx(
HKEY hKey, //已经打开键的句柄
LPCTSTR lpValueName, // 键项名称地址
DWORD Reserved, // 保留
DWORD dwType, // 键项数据类型
CONST BYTE *lpData, // 键项数据值的缓存地址
DWORD cbData //键项数据值的缓存大小
);
2) 取出键项值,可以使用下面的API。
LONG RegQueryValueEx(
HKEY hKey, //已经打开键的句柄
LPTSTR lpValueName, //键项名称地址
LPDWORD lpReserved, //保留
LPDWORD lpType, //键项数据类型
LPBYTE lpData, //要返回的键项数据值缓存地址
LPDWORD lpcbData //要返回的键项数据值缓存大小
);
3) 删除指定键项
LONG RegDeleteValue(
HKEY hKey, //已经打开键的句柄
LPCTSTR lpValueName //键项名称地址
);
4) 遍历一个子键下的所有键项
LONG RegEnumValue(
HKEY hKey, //已经打开键的句柄
DWORD dwIndex, // 索引
LPTSTR lpValueName, // 要返回的键项名称的缓存地址
LPDWORD lpcbValueName, //要返回的键项名称的缓存大小
LPDWORD lpReserved, // 保留
LPDWORD lpType, // 键项类型
LPBYTE lpData, // 要返回的键项值的缓存地址
LPDWORD lpcbData //要返回的键项值的缓存大小
);
四. 举例
下面来举两个例子,DllRegisterServer向注册表中添加几个键,并添加键项;DllUnregisterServer则将上面添加的几个键和它所有的键项从注册表中删除掉。
void _stdcall DllRegisterServer(void)
{
char ClassId[] ="CLSID//{FB2D0941-D73D-4cf5-A681-AD7339FC32CF}";
char DllPath[] = "C://Documents and Settings//qgmis//桌面//1.dll";
char ProgID[] = "MyProgID";
HKEY hKey, hKey0, hKey1;
DWORD ValueSize;
LONG hResult;
hResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, ClassId, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, NULL);
if (hResult != ERROR_SUCCESS) return;
ValueSize = strlen(DllPath) + 1;
hResult = RegCreateKeyEx(hKey, "InprocServer32", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey0, NULL);
if (hResult != ERROR_SUCCESS) return;
RegSetValueEx(hKey0, NULL, 0, REG_SZ, (PBYTE)DllPath, ValueSize);
ValueSize = strlen(ProgID) + 1;
hResult = RegCreateKeyEx(hKey, "ProgID", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey1, NULL);
if (hResult != ERROR_SUCCESS) return;
RegSetValueEx(hKey1, NULL, 0, REG_SZ, (PBYTE)ProgID, ValueSize);
RegCloseKey(hKey);
RegCloseKey(hKey0);
RegCloseKey(hKey1);
}
void _stdcall DllUnregisterServer(void)
{
char ClassId[] ="CLSID//{FB2D0941-D73D-4cf5-A681-AD7339FC32CF}";
LONG hResult;
HKEY hKey;
hResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, ClassId, 0, KEY_WRITE | KEY_READ, &hKey);
if (hResult != ERROR_SUCCESS) return;
RegDeleteKey(hKey, "InprocServer32");
RegDeleteKey(hKey, "ProgID");
RegCloseKey(hKey);
RegDeleteKey(HKEY_CLASSES_ROOT, ClassId);
}