注册表编程下,用不同的方法实现对其的读取与写入:
API:创建步骤:创建键RegCreateKey()或RegCreateKeyEx(),打开键RegOpenKey()或RegOpenKeyEx(),写入注册表RegSetvalue()或是RegSetvalue(),关闭RegCloseKey ()
读取步骤 打开键RegOpenKey()或RegOpenKeyEx(),读取数据RegQueryValue() 或RegQueryValueEx(),关闭RegCloseKey ()
注册表存储在二进制文件中,Win32 API提供了大量的函数以便应用程序访问注册表。
1、 创建键:
1.1 RegCreateKey(HKEY hKey, // 已经打开的父键句柄
LPCTSTR lpSubKey,// 要新建的子键的名称
PHKEY phkResult }// 新建的子键的句柄
1.2 RegCreateKeyEx(HKEY hKey, // 已经打开的父键句柄
LPCTSTR lpSubKey,// 要新建的子键的名称
DWORD ulOptions, // 保留 (一般都是0)
LPCTSTR lpClass,// 指向键的类别的字符串。如果键已经存在了,则该参数被忽略
REGSAM samDesired, // 安全访问掩码
LPSECURITY_ATTRIBUTES lpSecurityAttributes;该参数决定返回的键句柄是否能被子进程继承
PHKEY phkResult ,// 新建的子键的句柄
LPDWORD lpdwDisposition; // 如果是REG_CREATED_NEW_KEY:如果键不存在则创建;如果是 REG_OPENED_EXISTING_KEY:如果键已存在则打开该建;
)
2、 打开键:
2.1 RegOpenKey(HKEY hKey, // 已经打开的父键句柄
LPCTSTR lpSubKey, // 待打开的子键的名称
PHKEY phkResult ) // 打开的子键的句柄
2.2 LONG RegOpenKeyEx(HKEY hKey, // 已经打开的父键句柄
LPCTSTR lpSubKey, // 待打开的子键的名称
DWORD ulOptions, // 保留 (一般都是0)
REGSAM samDesired, // 安全访问掩码
PHKEY phkResult // 打开的子键的句柄);
3、 写入注册表:RegSetValue(默认REG_SZ类型),RegSetValueEx(其他类型)
3.1RegSetValue(HKEY hKey, // 已经打开的父键句柄
LPCTSTR lpSubKey,// 待写入的键值名
DWORD dwType, //要设置的键值类型
LPBYTE lpData, //键值数据
DWORD cbData)//键值数据长度
3.2 RegSetValueEx(HKEY hKey,
LPCTSTR lpValueName,
DWORD Reserved,//默认为0
DWORD dwType,
LPBYTE lpData,
DWORD cbData)
4、 由注册表中读数据:RegQueryValue(默认REG_SZ类型),RegQueryValue Ex(其他类型)
4.1RegQueryValue( HKEY hKey,
PCTSTR lpSubKey,
LPTSTR lpValue,
PLONG lpcbValue}
4.2LONG RegQueryValueEx( HKEY hKey, // 已经打开的父键句柄
LPCTSTR lpValueName, // 待读出的键值名
LPDWORD lpReserved,
LPDWORD lpType,//读出的键值类型
LPBYTE lpData,//读出的键值数据
LPDWORD lpcbData)//读出的键值数据长度
5 关闭注册表 RegCloseKey(HKEY hKey );
6. 删除子键 ReDeleteKey(HKEY hKey, LPCTSTR lpValueName);
7. 删除子键值 ReDeleteValue(HKEY hKey, LPCTSTR lpValueName);
8. 设置 子键的安全性 RegSetKeySecurity(hKey, OWNER_SECURITY_INFORMATION, &Security);
其中,Security是SECURITY_DESCRIPTOR结构的一个对象。除上面使用的WRITE_OWNER之外,对注册表键的访问权限还
有DELETE、READ_CONTROL、WRITE_DAC等标准访问权限以及注册表所专有的访问权限KEY_CREATE_LINK、
KEY_CREATE_SUB_KEY、KEY_EXECUTE、KEY_ENUMERATE_SUB_KEYS、KEY_NOTIFY、KEY_QUERY_VALUE、
KEY_SETVALUE、KEY_ALL_ACCESS、KEY_READ和KEY_WRITE等。
9. 保存子键信息到一个文件中
RegSaveKey(HKEY hKey, LPCTSTR lpFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
lpFileName注意这个文件必须是不存在的,而且也不能有扩展名(否则RegRestoreKey()函无法读取)。
在使用这个函数时需要有SE_BACKUP_NAME权限,而这个权限是不可以在RegOpenKey()或是RegCreateKeyEx()中指定的。要做到这一点就必须提升程序的权限,其具体实现如下代码如示:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
char strKey[]="Software\Microsoft\Internet Explorer";
LPTSTR szSaveFileName;
HKEY key;
// 申请备份权限
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
return;
LookupPrivilegeValue(NULL,SE_BACKUP_NAME,&tkp.Privileges[0].Luid);//申请SE_BACKUP_NAME权限
tkp.PrivilegeCount=1;
tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
//开始备份工作
szSaveFileName=LPTSTR("D:\KeyDate"); //注意文件不可存在否则无法成功
RegOpenKeyEx(
HKEY_CURRENT_USER,
(LPCTSTR)strKey,
0,
KEY_ALL_ACCESS,
&key);
RegSaveKey(key,szSaveFileName, NULL);
RegCloseKey(key);
}
10.从一个文件中恢复子键信息到注册表
RegRestoreKey(HKEY hKey, LPCTSTR lpFileName, DWORD dwFlage);
此函数的前两个参数可以与RegSaveKey相同,而参数dwFlage为TRUE<REG_WHOLE_HIVE_VOLATILE>的话,是暂时恢复注册表,如果为FALSE<REG_WHOLE_NO_VOLATILE>则是永久修改注册表值。同样需要注意的是使用这个函数需要有SE_RESTORE_NAME权限。
11. 枚举键值信息
枚举键值信息的方法与枚举子键信息极为相似,可以用RegEnumValue函数实现,其函数原型如下:
RegEnumValue(
hkey, //被枚举的键句柄
dwIndex, //子键索引编号
lpValueName, //键值名称
lpcbValueName, //键值名称长度
lpReserved, //系统保留,指定为0
lpType, //键值数据类型
lpDate, //键值数据
lpcbDate //键值数据长度
);
其实现代码如下:
for(dwIndex=0;dwIndex<NameCnt;dwIndex++) //枚举键值
...{
DateSize=MaxDateLen+1;
NameSize=NameMaxLen+1;
szValueName=(char *)malloc(NameSize);
szValueDate=(LPBYTE)malloc(DateSize);
/**//*参数定义请参照获取子键/键值信息部分...*/
RegEnumValue(hKey,dwIndex,szValueName,&NameSize,NULL,&Type,szValueDate,&DateSize);//读取键值
if(Type==REG_SZ)
...{
/**//*判断键值项类型并做其它操作......*/
}
if(Type==REG_DWORD)
...{
}
}
与枚举子键相似,在每次循环中应该重新设置 数据长度DateSize=MaxDateLen+1,键值名称长度NameSize=NameMaxLen+1。
11.枚举子键信息
枚举子键可以用API函数 RegEnumKeyEx来实现,调用RegEnumKeyEx时将返回子键的名称、长度和一些相关数据。如果想得到一个键下的全部子键的话应该循环调用,直到返回ERROR_NO_MORE_ITEMS为至,就说明已经枚举完了所有数据。
其函数原型如下:
RegEnumKeyEx(
hkey, //被枚举的键句柄
dwIndex, //子键索引编号
lpName, //子键名称
lpcbName, //子键名称长度
lpReserved, //系统保留,指定为0
lpClass, //子键类名
lpcbClass, //子键类名长度
lpftLastWriteTime//最后写入时间
);
因为在之前我们已经通过RegQueryInfoKey函数获取了键的有关数据,所以在这里不再跟据ERROR_NO_MORE_ITEMS来实现了。
其实现代码如下:
for(dwIndex=0;dwIndex<KeyCnt;dwIndex++) //枚举子键
...{
KeySize=KeyMaxLen+1; //因为RegQueryInfoKey得到的长度不包括0结束字符,所以应加1
szKeyName=(char*)malloc(KeySize);
/**//*参数定义请参照获取子键/键值信息部分...*/
RegEnumKeyEx(hKey,dwIndex,szKeyName,&KeySize,NULL,NULL,NULL,NULL);//枚举子键
printf(szKeyName);
}
最后需要注意的是在每次调用RegEnumKeyEx前必须重新将KeySize的值设为KeyMaxLen缓冲区的大小,因为每次函数返回时KeySize的值会变成返回的键值的名称长度,随着循环次数这个值会变小,而可能出现无法枚举所有键值项的情况。
01 void CFileView::OnRegWrite()
02 {
03 HKEY hKey;
04 RegCreateKey(HKEY_LOCAL_MACHINE,"SoftWare\\www.colsir.com\\admin",&hKey);
05 RegSetValue(hKey,"1111",REG_SZ,"pan",strlen("pan"));
06 RegCloseKey(hKey);
07 }
08 void CFileView::OnRegRead()
09 {
10 LONG lValue;
11 RegQueryValue(HKEY_LOCAL_MACHINE,"SoftWare\\www.colsir.com\\admin",NULL,&lValue);//
如果数据是不需要的这个参数可以为空
12 char *pBuf=new char[lValue];
13 RegQueryValue(HKEY_LOCAL_MACHINE,"SoftWare\\www.colsir.com\\admin",pBuf,&lValue);
14 MessageBox(pBuf);
15 }
BOOL GetLocalThenCopySet()
{
BOOL bLocalThenToDest = FALSE;
DWORD
dwDisposition,dwType,dwDest,dwSize = sizeof (DWORD);
HKEY
hKey;
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\sony\\Compile\\"),0L,NULL,REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,NULL,&hKey,&dwDisposition) == ERROR_SUCCESS)
{
if(RegQueryValueEx(hKey,_T("LocalThenCopy"),NULL,
&dwType,(BYTE *)&dwDest,&dwSize) == ERROR_SUCCESS)
{
bLocalThenToDest = dwDest;
}
else
{
RegSetValueEx(hKey,_T("LocalThenCopy"), 0L, REG_DWORD,
(CONST BYTE*) &bLocalThenToDest, sizeof(DWORD));
}
}
RegCloseKey(hKey);
return bLocalThenToDest ;
}