看到论坛好多人问win7下写注册表的问题,我结合自己的理解写了一点东西,首先声明一下,本人初学Delphi,水平有限,大家见笑了,有什么不对之处请老鸟多指点。
[背景]
win7/Vista提供的UAC机制,是win7/Vista的新增功能之一。它的主要目的是防止对于操作系统本身的恶意修改。如果想对于win7/Vista的系统设置进行改动,必须通过UAC的验证才能够进行。通过这样的手段,大大提供了系统的安全性。关于UAC的利弊,网络上的说法褒贬不一,在这里就不具体讨论了。
[应用]
Delphi写的程序一般都可以在win7/vista上运行,但是有关注册表、程序文件夹的操作会无声的失效,这给普通用户带来很大不便,他们并不明白什么时候程序需要写注册表(因为没有提示),需要以管理员身份运行程序!现在大多数Delphier还是停留在D7的阶段,这时候一般大家都会把责任推给D7,是D7太老了,不支持Win7/Vista! 在试了D2007后,发现依然不行,于是感慨说Delphi对win7/vista支持不好,事实真是这样吗?
打开D2007(sorry,现在机子上没用以后的版本,我想应该相同)的目录:\source\Win32\vcl,找到winxp.pas这个单元,用记事本打开发现它引用了winxp.rc, 再用记事本打开windows.rc, 发现它编译的是 sample.manifest 这个文件,用记事本打开它,看到是用xml这样描述的:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="DelphiApplication"
version="1.0.0.0"
processorArchitecture="*"/>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
publicKeyToken="6595b64144ccf1df"
language="*"
processorArchitecture="*"/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
对比D7相同的文件,发现多了<trustInfo>项的,这也就是所谓的支持UAC的关键,查阅msdn有关VC2008的manifes的设置,有关权限的说明如下:
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
这里要注意的是requestedExecution Level的值,一般用asInvoker或requireAdministrator,普通的程序应该用asInvoker来执行,意思是按照目前你登陆win7/Vista帐号的权限执行,requireAdministrator顾名思义就是需要你启动管理员权限才能执行。这里是win7/Vista会不会跳出UAC提示窗口的重点。
1)如果用asInvoker应该就不会再提示了,我觉得这是个鸡肋!因为win7/vista默认是不以administrator登陆的,登陆的帐号根本没有太多权限!你的程序如果操作了注册表、程序文件夹的话当然在这个帐号下会无声的失效;
2)在VC2008中,程序中如果没有manifest,则默认为requireAdministrator权限(爽呀!),requestedExecutionLevel为 requireAdministrator的可执行文件前面都会有一个小盾牌提醒使用者。好了,看到这里,大家应该明白了吧!
[解决方法]
对于D7,解决方法太简单了。如果你操作了注册表之类的“危险地带”的话,就要使用这个来提醒你的用户要以管理员权限运行,其实这个网上早就有了,我又拷过来了:)
1.建立 res 文件
建立一个文本文件,名字可以自己起,我这里叫:UAC.manifest,内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
建立文本文件,名为 UAC.rc,内容:
1 24 UAC.manifest
编译成 uac.res 文件,运行:
brcc32 uac.rc -fouac.res
2.在代码中引入
打开项目文件,加入
{$R uac.res}
3.编译程序
或者你还可以仿照xpman.pas写个VistaUAc.pas,其中引用以上资源,编译后将相应的dcu拷入lib文件夹,vistUac.pas拷入vcl文件夹,需要时,你可以在工程或单元中像引用xpman一样方便地uses VistaUac!
对于D2007(sorry,以后的版本没有试,因为本机没装,应该也一样)有些麻烦,因为它默认是启用所谓的Runtime themes的,以上uac.res是没办法正常引用的,解决方法有两种:1)关闭runtime themes才能正常引用, 但程序没有xp特效了,郁闷了吧!2)用D7的winxp.res,xpman.pas覆盖D2007的,重新编译D7的xpman.pas生成的dcu覆盖2007的(建议备份!), 当需要编写修改“危险地带”程序时,放弃使用runtime themes,转而uses xpman和引用以上资源,程序xp特效又回来了,久违的小盾也出现了!
PS:用Dejoy 的D7lite7.3里的winxp.res不行,因为他已经改过了,内容和D2007的是一模一样的,不能和uac.res 共存!
[结论]
以上解决方法并非是非完美的,UAC的提示或多或少给用户带来了不安全的感觉,最好的方法应该由程序本身和用户交互说明需要使用管理员权限运行,或者自己你像在xp以下系统上一样,自己提高权运行权限,实现一些操作,但这样做并非现实,MS能会让它的辛苦研发出的UAC项目形同虚设?MS最终的想法可能是要大家都向它申请数字签名。
以上有什么不对之处,请指正。
[写在最后]
Borland及CG真的太好了,每次更新都巴不得把大家项目中所用的控件全提供了,以致于现在倒像是个制作控件的公司,每次基本都是几个控件升级,编译器很少改动!授之以鱼不如授之以渔,Delphi让很多人养成了一种习惯,遇到问题先去想有没有什么控件可以实现,有的人编程就是用VCL控件堆积木,还到处挑VCL的bug,真是深在福中不知福呀!源代码都给你了,你不会学着改吗?你要是用用VC,好多都要从头做起,编程好像是直接在用api(程序当然执行效率高了,可真没效率),MFC不是真正面向对象,写个界面能把人急疯了,你会真觉得Delphi太好了!可人家MS也知道自己家的东西烂,编了庞大的MSDN让它的程序员模仿,有如老师亲临,大大给他的用户壮了胆,也给了他们创造了更广阔的想象空间... 扯远了,大家见笑了!