Delphi在win7/vista下写注册表等需要管理员权限的解决方案
看到论坛好多人问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让它的程序员模仿,有如老师亲临,大大给他的用户壮了胆,也给了他们创造了更广阔的想象空间... 扯远了,大家见笑了!
参考:http://m.blog.csdn.net/blog/fghydx/35218457
Delphi在win7/vista下写注册表等需要管理员权限的解决方案的更多相关文章
- delphi在64位系统下写注册表注意事项
HKEY_LOCAL_MACHINE写这个主键下的项,在64位系统下可能会重定向,所以构造时要加KEY_WOW64_64KEY reg := TRegistry.Create(KEY_WRITE or ...
- Win7,Vista UAC下应用程序标注为“需要管理员权限”的四种方法(可以修改注册表)
[转]Vista UAC下应用程序标注为“需要管理员权限”的四种方法 在Microsoft 的UACBlog里对此有过叙述.总结如下: 首先,如果一个程序被识别为管理员程序时,Vista会在它的图标上 ...
- win7 64bit+vs2010 操作注册表
注册表五个根键 HKEY_CLASSES_ROOT--管理文件系统 HKEY_LOCAL_MACHINE--管理当前系统硬件配置 HKEY_LOCAL_USER--管理系统当前用户配置 HKEY ...
- VB6之写注册表
难免会遇到写注册表的情况,写了个实用点的RegWrite函数.为了减少代码量,用WScript.Shell取代了API来实现. 使用方式就在注释中了,就不再过多解释了.PS:注释比实现代码要丰富多了, ...
- IE 内使用ActiveX,写注册表被重定向到如下注册表
IE 内使用ActiveX,写注册表被重定向到如下注册表,所以使用注册表做标记要注意下,目前还没找为什么会这样 HKEY_CURRENT_USER\Software\Microsoft\Interne ...
- C++写注册表
1. 注册表简介 注册表是为Windows NT和Windows95中所有32位硬件/驱动和32位应用程序设计的数据文件,用于存储系统和应用程序的设置信息.16位驱动在Winnt (Win ...
- WinCE下读取注册表获得SD路径
WinCE下读取注册表获得SD路径 [要点]WinCE注册表中[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory\] 下键Folde ...
- Java Windows下读取注册表的工具类
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import ...
- 系统开启UAC情形下开机自启动程序如何以管理员权限启动
系统开启UAC情形下开机自启动程序如何以管理员权限启动 题记:本文阐述的是在Windows系统开启UAC的情况下,开机自启动程序需要以管理员权限启动, 系统弹出UAC对话框,用户同意的情形下启动程序 ...
随机推荐
- linux中的帮助命令 分类: linux 学习笔记 ubuntu 2015-07-05 19:07 31人阅读 评论(0) 收藏
说实话,到目前为止我还是不太习惯使用linux自带的帮助文档,遇到问题都是去查我自己下载的chm格式的命令大全,不过这些帮助命令我们还是有必要了解的. 1.man [要查看的命令名称] 例如想要查看l ...
- 文件MD5查看器工具与源码实现及下载
由于工作中经常需要查看文件的MD5值,先前网上找了几个MD5值查看工具,但基本都是选择文件,还没有复制功能,于是今天我就自己编写了个MD5查看工具,支持文件拖拽查看,并可以复制功能. 由于本工具比较小 ...
- AndroidStudio怎么将开源项目发布到jcenter
前言 自己在网上搜了一大堆,大体就两种方法,而我选择的是其中代码少的的方法,不过他们或多或少留下了少许的坑,(按他们的方法我是上传成功,但不能发布到jCenter上去,也可能是我自己的问题o(≧v≦) ...
- IIS Shared Configuration
Introduction The Internet changes the ways in which companies handle their day-to-day business and h ...
- mac下通过docker搭建LEMP环境
在mac下通过docker搭建LEMP环境境 1.安装virtualbox.由于docker是在lxc环境的容器 2.安装boot2docker,用于与docker客户端通讯 > brew up ...
- 关于jquery获取服务器端xml数据
其实这个很简单,但是有时候简单的东西会让你犯一些低级错误. 今天写了个spring mvc 的服务器端接口,主要是用来共享一些数据库数据. 请求字段:http://localhost:8080/XXX ...
- 当前时间 js
当前时间-倒计时下载 效果: 代码: <!doctype html> <html> <head> <meta http-equiv="Content ...
- 查看alter错误,grep -A,-B,-C的妙用
alert 日志记录了数据库的很多重要信息,要养成时常检查alert日志的习惯,但如果日志很大vi打开翻来覆去找着麻烦,怎么做的可以查错呢? 看我的测试 [oracle@ahjcyl-db bdump ...
- C# 基础 知识点
类型 1.decimal为高精度浮点数,常用于货币计算,然后它不是基本类型,所以性能相对float和double要差. 2.@用于字符串前使转义字符 \ 无效,甚至能将回车当作换行符直接赋值给字符串 ...
- QT QString转char*,char*转QString;简单明了,看代码。
//原始QStringQString qs = QString::fromLocal8Bit("我的");std::string strQs = qs.toStdString(); ...