注册表编程技术.docx

上传人:b****5 文档编号:5616588 上传时间:2022-12-29 格式:DOCX 页数:85 大小:86.45KB
下载 相关 举报
注册表编程技术.docx_第1页
第1页 / 共85页
注册表编程技术.docx_第2页
第2页 / 共85页
注册表编程技术.docx_第3页
第3页 / 共85页
注册表编程技术.docx_第4页
第4页 / 共85页
注册表编程技术.docx_第5页
第5页 / 共85页
点击查看更多>>
下载资源
资源描述

注册表编程技术.docx

《注册表编程技术.docx》由会员分享,可在线阅读,更多相关《注册表编程技术.docx(85页珍藏版)》请在冰豆网上搜索。

注册表编程技术.docx

注册表编程技术

SomeTipsforRegistryProgramming

作者:

osmose(ph4nt0m)

来源:

幻影旅团()&&补天网()

EMAIL:

osmose@

2003.7.18

写在前面的话

不敢给这篇文章起个太大的名字,毕竟这只是我这一段时间学习心得的一点总结,顶多仅仅是一些tips而已。

其实我什么都不懂,所以我尽量写的详细,希望大家不要厌烦。

注册表编程其实并不是一件困难的事情,如果看一点材料,查一查msdn,本可以很快掌握。

我在网上搜索了一下,发现很多高手提供的只是MFC的一个关于注册表的类,都很泛泛,真正的代码还需要自己添加。

对于像我一样急功近利,希望一口吃成胖子的菜鸟们,如果很快上手是大家最关心的问题。

说实话,我没有找到一个比较详细的说明,所以我开始写这篇文章,手边有的就是一个API函数表和MSDN。

在此感谢CSDN上各位大牛(Skt32(Skt32),shilong(星矢の诗龙),firela(firela),laolaoliu2002(老刘)等)对我的指点,那里也许是一个对程序爱好的人最应该去的地方之一。

也感谢幻影旅团的各位弟兄的帮助,那是一个只关心技术的地方。

或许这些知识都很浅显,但是我们在学习。

这篇文章最初的目的是写出一些属于自己的程序,或许适合热衷于开启别人机器某个服务的人,学会编写一些程序操作注册表,也许就不用总等着拾人牙慧了。

随着点滴的积累,逐渐觉得有更多的东西可以深挖或者涵括,于是就有了这篇整理的总结。

我从自己学习的角度,对遇到的困难尽可能的分析,给出结果。

但是文中仍然遗留了一些问题无法解决。

如果您有什么建议,欢迎指正。

 

BTW:

文中的程序如无特殊说明,都是支持MFC的。

新建项目时请注意。

第一章

概述

先让我们活动一下脑筋,想想看要修改或者保存注册表,有哪些途径?

1.在windows下面打开运行窗口(按住win键和r键),输入regedit,OK,在FILE菜单里有导入导出,保存什么,修改什么,不多说了。

2.到古老的DOS方式,让我们重新幼稚一下。

(下面的内容前人已经写过多次,抄过来用一下,像前辈们致敬!

在DOS提示符下键入Regedit命令,将出现一个帮助屏幕。

此屏幕给出了其命令行参数及其使用方法。

 语法:

Regedit[/L:

system][/R:

user]filename1

       Regedit[/L:

system][/R:

user]/Cfilename2

       Regedit[/L:

system][/R:

user]/Efilename3[regpath]

 其中:

  /L:

system指定system.dat文件的存放位置。

  /R:

user指定user.dat文件的存放位置。

    filename1指定引入注册表数据库的文件名。

  /Cfilename2指定形成注册表数据库的文件名。

  /Efilename3指定导出注册表文件的文件名。

 regpath指定导出注册表文件的开始关键字(缺省为全部关键字)

 现举几个例子说明regedit.exe在DOS下的使用方法。

 【例1】将系统注册表数据库registry导出到reg1.reg文件中。

  regedit/Ereg1.reg

 【例2】reg1.reg形成系统注册表数据库registry(全部)中。

 regedit/Creg1.reg

 【例3】将reg.dat引入系统注册表数据库中(部分)。

 regeditreg.dat

 【例4】将CJH开始的关键字导出注册表数据库,并命名为cjh.reg。

 

  regedit/Ecjh.regcjh

  【例5】指定system/dat存放在D:

\PWIN中和user.dat存放在E:

\PWIN中,将reg.dat数据文件形成一个新的注册表数据库registry。

  regedit/L:

D:

\PWIN/R:

E:

\PWIN/Creg.dat

DOS下的手段当然不止这些,如果想体验程序的感觉,还需要麻烦你看看批处理:

  @echooff

  path=c:

\windows;c:

\windows\command;c:

\dos

  cls

  echo正在导出注册表……

  regedit/Etxt.regHKEY_CLASSES_ROOT\txtfile

  echo.

  echo注册表导出完毕!

按任一键开始编辑注册表……

  echo.

  pause

  edittxt.reg

  echo正在将修改后的注册表导入……

  regedittxt.reg

  echo恭喜您!

在MS-DOS方式下成功修改了注册表!

  pause

  cls

  @echoon

把上面这段代码复制到一个.bat文件中,你可以用EDIT这个命令编辑。

从某种意义上说,充分发挥EDIT编辑器的强大功能,我们可以在遵循导出的注册表文件的格式的前提下,对注册表进行随心所欲的修改、删除或者增加任一子键。

如果觉得这还不够程序化,您可以发挥DOS环境下各种程序设计语言的优势,加上交互性的界面,将这一过程真正的程序化,应该丝毫不亚于Windows状态下的利用API函数做出来的效果。

3.在C程序中调用regedit命令,不要忘记C程序可以调用DOS命令的哟。

记得加入

#includeDOS.h

这种方法和上面一种比起来换汤不换药,不多说了。

3.MFC有专门操作注册表的库,据说很方便,我没有用过,因为我不会MFC,也许只是那几个类吧,也许有很多。

没做过的东西,就不能说它简单。

如果哪位高人研究过,请补充一下。

4.调用API函数。

API函数是个好东西,VB,Delphi,BCB,什么都可以用它。

有人建议最后学API,因为最难。

是的,可是我急功近利,只学那几个注册表的函数,试试看能不能学到点什么。

好了,上面是关于修改注册表的一些方法。

下面让我们来看看注册表函数都有哪些。

键管理类

RegCloseKey()

RegCreateKey()

RegCreateKeyEx()

RegDeleteKey()

 

RegDeleteKeyEx()

RegOpenKey()

RegOpenKeyEx()

 

值管理类

RegDeleteValue()

RegQueryValue()

RegQueryValueEx()

RegSetValue()

 

RegSetValueEx()

 

 

 

查询计数类

RegQueryInfoKey()

RegEnumKey()

RegEnumKeyEx()

RegEnumValue()

备份/恢复类

RegLoadKey()

RegReplaceKey()

RegRestoreKey()

RegSaveKey()

实用类

RegConnectRegistry()

RegNotifyChangeKeyValue()

RegUnloadKey()

安全类

(仅适用于NT)

RegGetKeySecurity()

RegSetKeySecurity()

 

我会选其中的一部分作具体介绍,这个文章能写到什么地步,能不能全部写完,我也不知道,看大家的反映了。

大家都知道,2001年微软停止开发win98系统内核,专攻NT,上面的一些函数还有专门服务于win3.1的,够古老的吧。

比如,RegSetValueEx()和RegSetValue()有什么不同呢?

前者可用于基于win32系统的应用开发。

RegSetValue()则是服务于win3.1系统的。

使用的时候要注意:

WindowsNT:

HKEY_PERFORMANCE_DATA

Windows95andWindows98:

HKEY_DYN_DATA

这两个子键是不一样的,虽然其他的都一样(HKEY_CLASSES_ROOT,EY_CURRENT_CONFIG,HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_USERS)

不要误会,这两个函数都可以用在95,98系统上,具体什么差别呢,看看MSDN的话:

Win32-basedapplicationsshouldusetheRegSetValueExfunction,whichallowsyoutosetanynumberofnamedvaluesofanydatatype.(基于win32的应用程序推荐使用RegSetValueEx函数,可以对设置任意类型任意键名任意值。

)所以,以后有带Ex的函数,我们尽量都用它啦。

OK,第一部分先写到这里。

第二部分,我会给出一个完整的例子,如何保存注册表里任意一个键和他的所有子键,里面涉及到一些权限的问题,调用了一些API函数获得操作注册表的权限。

第三部分,引用并且分析MSDN中的一个例子,通过注册表列举函数保存HKEY_LOCAL_MACHINE这样一个大键。

第四部分是关于修改注册表键值,也有一个具体的例子,同时可能会谈到一点创建子键的问题,希望让大家都能看得轻松一点。

我会结合MSDN中的解释尽量把每一个函数讲清楚,至少是我遇到的问题都说清楚。

第二章

保存注册表的特定键

这一部分,我们来看看如何保存注册表里任意一个键以及它的所有子键。

所需要用到的函数是RegOpenKeyEx,RegSaveKey和RegCloseKey。

看他们的名字,你也可以看出来他们是做什么用的。

RegOpenKeyEx负责打开指定的键。

在后文,也许我们会用到另一个函数打开某个特定的键:

RegCreateKeyEx。

这里先把他们做一个比较:

这两个函数都适用于基于win32的应用程序,都可以打开指定子键。

所不同的是,当指定子键不存在时,RegCreateKeyEx会自动生成这个键,而RegOpenKeyEx仅仅是负责打开。

如果指定键不存在,RegOpenKeyEx返回失败信号。

下面,让我们看看具体的操作:

LONGRegOpenKeyEx(

HKEYhKey,//用于打开键的句柄

LPCTSTRlpSubKey,//储存打开子键名称的变量的地址

DWORDulOptions,//保留值

REGSAMsamDesired,//访问形式

PHKEYphkResult//句柄的地址

);

这个函数是一个long型函数,如果执行成功,会返回ERROR_SUCCESS。

为了大家看得明白,我把每个变量都解释一下,磨刀不误砍柴工。

HKEYhKey:

这个句柄其实就是下面几个东西里的一个,打开注册表,大家对他们都不陌生吧。

HKEY_CLASSES_ROOT

HKEY_CURRENT_CONFIG

HKEY_CURRENT_USER

HKEY_LOCAL_MACHINE

HKEY_USERS

WindowsNT:

HKEY_PERFORMANCE_DATA

Windows95andWindows98:

HKEY_DYN_DATA

LPCTSTRlpSubKey:

LPCTSTR是一个指向字符串常量的一个32位指针类型,字符可以是Unicode和DBCS。

lpSubKey里可以放指针,也可以用变量,就像本文所用的。

DWORDulOptions:

这个没什么好说的,保留值,永远都是0,如果你想要继续干活的话。

REGSAMsamDesired:

访问形式,可以有下面几个值:

Value

Meaning

KEY_ALL_ACCESS

包括KEY_QUERY_VALUE,KEY_ENUMERATE_SUB_KEYS,KEY_NOTIFY,KEY_CREATE_SUB_KEY,KEY_CREATE_LINK和KEY_SET_VALUE.

KEY_CREATE_LINK

Permissiontocreateasymboliclink.(我不太明白)

KEY_CREATE_SUB_KEY

可以生成子键

KEY_ENUMERATE_SUB_KEYS

可以枚举子键

KEY_EXECUTE

可读

KEY_NOTIFY

Permissionforchangenotification.(也不太明白,没用过)

KEY_QUERY_VALUE

可查询键值

KEY_READ

包括KEY_QUERY_VALUE,KEY_ENUMERATE_SUB_KEYS和KEY_NOTIFY.

KEY_SET_VALUE

可改变键值

KEY_WRITE

包括KEY_SET_VALUE和KEY_CREATE_SUB_KEY.

PHKEYphkResult:

函数生成的指向打开键的一个句柄,后面的RegSaveKey函数就要用到它。

使用完毕后,我们需要用RegCloseKey回收。

解释完了RegOpenKeyEx函数,让我们看看如何回收句柄RegCloseKey:

LONGRegCloseKey(

HKEYhKey//需要回收的句柄,就是上文的“PHKEYphkResult”

);

如果函数执行成功,返回值也是ERROR_SUCCESS。

另外一个回收句柄的函数是RegFlushKey。

退出前,RegFlushKey会往注册表里写一些信息,这个步骤可能会需要好几秒,机器需要完成一个从内存写入硬盘的过程,同时,这个函数会占用大量的系统资源,非必要时不要使用。

RegCloseKey则是一个退出迅速的家伙,不会拖泥带水,“我们一直都用它”:

D

现在你可能对打开一个键和关闭一个键都有点了解了,下面是操作的重点,打起精神来吧:

LONGRegSaveKey(

HKEYhKey,//所要备份键的句柄

LPCTSTRlpFile,//储存文件的指针

LPSECURITY_ATTRIBUTES//生成文件的安全权限

);

HKEYhKey:

就是我们用RegOpenKeyEx得到的那个新句柄。

LPCTSTRlpFile:

这个函数把一个键和他的所有子键存储到一个文件中,这里的lpFile代表文件名的变量的地址,不过你也可以直接把文件名放在这里,我会show给你看的。

LPSECURITY_ATTRIBUTES:

这个东西说来话长,MSDN专门开了一页解释SECURITY_ATTRIBUTES这个东西,感兴趣的朋友可以自己看看,我们这里用得很简单,NULL就可以了。

使用NULL意味着生成文件遵从默认的安全准则。

好了,呼出一口气,枯燥的教条终于完了。

也许你已经跃跃欲试了。

好,就让我们写一个简单的程序。

测试条件:

VC6.0,WindowXPPrefessional,登陆账号:

管理员(这个条件后面会提到)

#include"stdafx.h"

#include"windows.h"

#include"stdio.h"

#include"stdlib.h"

voidmain()

{

CStringstrKey="Software\\Microsoft\\InternetExplorer\\Main";

LPTSTRszSaveFileName;

HKEYhResult;

szSaveFileName=LPTSTR("1.dat");//要保存的文件名

RegOpenKeyEx(

HKEY_CURRENT_USER,

(LPCTSTR)strKey,

0,

KEY_ALL_ACCESS,

&hResult);//获得句柄

RegSaveKey(hResult,szSaveFileName,NULL);//保存键值

RegCloseKey(hResult);//释放句柄

}

没错就是这么简单,如果你仔细阅读了上面的讲解,看懂这一段一定没有问题。

编译通过,没有问题。

以后就可以这样照葫芦画瓢了。

你要做的只是把

CStringstrKey="Software\\Microsoft\\InternetExplorer\\Main"和RegOpenKeyEx里的“HKEY_CURRENT_USER”换成你要保存的键就可以了。

运行吧,你会看到当前目录下生成了一个1.dat文件。

成功了?

仔细看看文件大小。

0K?

!

!

怎么回事?

一定是哪里出了错误。

我们一共就调用了三个函数,是哪一个出错了呢?

加入一些语句调试一下。

#defineERROR111

#defineERROR222

#defineERROR333

#defineSUCCESS44

if(RegCreateKeyEx(

HKEY_LOCAL_MACHINE,

(LPCTSTR)strKey,

0,

NULL,

REG_OPTION_NON_VOLATILE,KEY_CREATE_SUB_KEY|KEY_WRITE|KEY_READ,

NULL,

&Result,

NULL)!

=ERROR_SUCCESS)

{

cout<<"ErrorOpeningRegister...\n";

returnERROR1;

}

if(RegSaveKey(Result,szSaveFileName,NULL)!

=ERROR_SUCCESS)

{

cout<<"ErrorsavingRegister...\n";

returnERROR2;

}

RegCloseKey(Result);

returnSUCCESS;

 

注意,这里我换用了RegCreateKeyEx这个函数,只是想show一下这个函数的用法。

大家可以跳过去,或者依然是用RegOpenKeyEx。

最后发现,在调用RegSvaeKey的时候出错了。

所有的这一些都是按照MSDN上的指示一步步来的,语法也没有问题,那会是哪里的原因呢?

我在RegSaveKey后面使用了一段测试代码,发现运行的时候,系统提示没有权限备份注册表。

请注意,我可是用管理员的身份登陆XP的……真正的原因我们还是要去权限里找(在MSDN里搜索WindowsNTPrivileges,可以看到相关的东西)。

这里简单说一下,在NT/2K/XP下失败的原因是没有SE_BACKUP_NAME权限。

我们需要加入下面一段代码(基本功能是开一个线程申请权限,具体的恕不多介绍了,以后大家只要直接加入就可以了)。

HANDLEhToken;

TOKEN_PRIVILEGEStkp;

if(!

OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))

return;

LookupPrivilegeValue(NULL,SE_BACKUP_NAME,&tkp.Privileges[0].Luid);

tkp.PrivilegeCount=1;

tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);

好了,大家辛苦了。

完整的程序如下:

#include"stdafx.h"//请千万不要忘记

#include"windows.h"//这两个头文件

#include"stdio.h"

#include"stdlib.h"

voidmain()

{

CStringstrKey="Software\\Microsoft\\InternetExplorer\\Main";

LPTSTRszSaveFileName;

HKEYhResult;

//申请备份权限

HANDLEhToken;

TOKEN_PRIVILEGEStkp;

if(!

OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))

return;

LookupPrivilegeValue(NULL,SE_BACKUP_NAME,&tkp.Privileges[0].Luid);

tkp.PrivilegeCount=1;

tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);

//开始备份工作

szSaveFileName=LPTSTR("1.dat");

RegOpenKeyEx(HKEY_CURRENT_USER,(LPCTSTR)strKey,0,KEY_ALL_ACCESS,&hResult);

RegSaveKey(hResult,szSaveFileName,NULL);

RegCloseKey(hResult);

}

好了,到目前为止,我们已经学会了如何备份一个子键。

可是如何备份整个HKEY_CURRENT_USER乃至于整个注册表呢?

这是我们第三部分的内容。

下一讲我们将会学到如何枚举所有的子键,并且结合MSDN上的一个例子,给大家做一个分析,同时也对这一讲的内容作一个复习。

Thankyousomuchforreadingthisarticle.

===============================================================

附录:

测试出错的代码:

longt=RegSaveKey(Result,szSaveFileName,NULL);

{

LPVOIDlpMsgBuf;

FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER|

FORMAT_MESSAGE_FROM_SYSTEM|

FORMAT_MESSAGE_IGNORE_INSERTS,

NULL,

t,

MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),//Defaultlanguage

(LPTSTR)&lpMsgBuf,

0,

NULL);

AfxMessageBox((LPCTSTR)lpMsgBuf);

LocalFree(lpMsgBuf);

}

第三章保存整个注册表

PARTI一个MSDN上的例子

上次我们学习了如何保存一个子键以及其所有从属子键。

不过,你有没有想过要备份整个HKEY_LOCAL_MACHINE这个根键或者整个注册表五个根键呢?

上一次的方法如果你试试看,就会发现不适用了,呵呵。

今天我打算结合MSDN上的一个例子谈一谈远程备份注册表的问题。

学会远程备份,结合下一次的内容(修改注册表),大家可能自己就能够写程

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 营销活动策划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1