首页 > 代码库 > UAC相关问题分析--使用管理员权限打开VisualStudio,无法访问网络磁盘,无法拖拽文件
UAC相关问题分析--使用管理员权限打开VisualStudio,无法访问网络磁盘,无法拖拽文件
搬运自http://wurang.me/2014/06/17/uac-problems.html
【问题产生】
问题最初是在administrator权限下,visual studio 打开网络磁盘下的文件报错。经过几次调试,最终发现是问题是在管理员权限下,vs无法访问网络磁盘。
Console.Write( System.IO.File.Exists(path));
该结果返回False。为了确认是由于权限问题引起,使用非管理员权限打开vs,运行上面的程序,结果返回True。
至此问题确立:win7/win8下,使用管理员权限打开VisualStudio,无法访问网络磁盘。
【问题分析】
首先让我想到的是很久之前,发现用管理员权限打开VisualStudio后,没办法把文件直接拖拽到VS中打开,我的理解是,管理员权限下的VS比普通文件有更高的“安全级别”,windows不允许从低级别向高级别发送调用命令,事实上也确实如此。
解决方案一:使用系统administrator账户
实验一:
- 进入C:\Windows目录
- 找到并打开notepad.exe(用户权限)
- 拖拽其他文本文件到打开的记事本应用,发现是可以正常打开的,然后关闭所有文件
- 右键以管理员权限打开notepad.exe
- 再拖拽同样的文本文件到记事本应用,这时候可以看到是没有办法将文件拖拽进来的
知道问题由权限引起,那么接下来就是如何设置权限。
由于VS是管理员权限而其他文件是用户权限,所以考虑使用administrator账户,让所有文件都拥有管理员权限。
- 运行
lusrmgr.msc
- 本地用户和组--用户--administrator--去掉“账号已禁用”的勾,确认退出
- 切换用户,使用administrator用户登录
ps:win7家用版没有lusrmgr.msc
,开启administrator的方法这里不再细说。
这时候所有文件都拥有管理员权限,测试一下问题,发现可以正常返回True了。但使用Administrator是一种不安全的方式。而且也比较麻烦,所以继续探究解决方案。
解决方案二:干掉UAC
在网上看到一篇论文《Vista系统管理员权限下文件禁止拖拽解决方案》,这和我的问题非常相近,文章提了三点:介绍UIPI,提出修改注册表的方式解决问题,提出使用windows api方式解决问题。
UIPI:User Interface Privilege Isolation(用户界面特权隔离),详细的介绍可以参考微软白皮书,简单来说,它是UAC的核心,做安全权限用的。说到这里,问题更专业化了,MSDN的Blog中有人遇到了同样的问题(Pat‘s Windows Development Blog),这里面用专业的术语描述了我最开始的理解:
Lower Privilege Processes Can’t Interfere with Higher Privilege Processes
当然,里面也提出了解决方案:不要使用管理员权限,或者不要开启uac。
实验二:
在UIPI的微软白皮书中提到使用“Process Explorer”查看UIPI,这里也作为一个实验:
- 下载Process Explorer
- 打开Process Explorer,在GridView的Header上右键,选择Select Columns,勾选Integrity Level
- 观察所有应用的UIPI,如果是以普通用户权限打开,那么我们最多能看到Medium的level
- 如果用右键管理员打开,所有的UIPI才可以看到
这个实验也说明了低权限不能够访问高权限的问题。
现在回到论文中,里面提到通过修改注册表的方式关闭UIPI: 将HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\System
下的EnableUIPI
设置成0
进入注册表编辑器,发现并没有这样一个值,不过却发现了EnableLUA,其实EnableUIPI是visita下的值,而在win7/win8下则是EnableLUA.
把EnableLUA
的值设成0,重启计算机,然后以管理员权限运行VS,测试问题,结果返回True。其实关闭UAC和使用administrator账户是一样的效果,都是获取了最高权限,但都是不安全的,能不能寻找一个简单又安全的方法来解决问题?
ps:论文中提到的第三点是使用windows api,有兴趣的可以阅读ChangeWindowMessageFilter相关资料,其原理是将拖拽等操作添加到白名单,这样就不会被UIPI拦截。但我们的问题并不是拖拽问题,而是找不到路径,所以这里不再过多讨论。
解决方案三:在管理员权限下配置磁盘映射
经过上面的分析,对UAC逐步有了更深的理解,但想一想,跟UAC扯上关系,不管哪一种方法都麻烦,而且在调试中又发现了下面的问题:
实验三:
- 配置一个网络磁盘映射(Z盘)
- 用普通用户权限打开记事本或者VS---文件---打开,观察文件资源管理器。这里是可以看到Z盘的。
- 用管理员权限打开记事本或者VS---文件---打开,再观察文件资源管理器。发现根本就没有Z盘。
其实问题一开始就走弯路了,难怪System.IO.File.Exists(path)
会找不到路径,这里压根就没有Z盘。那我们在这里配置一下网络磁盘映射Y盘:
配置完成后可以看到Y盘了,然后运行一下程序,找找Y盘的路径,结果返回True。然而我们在“我的电脑”中却看不到Y盘,如果以普通用户权限打开文件资源管理器,也看不到Y盘(除非是administrator账户,Z盘Y盘都可见),这么说来,管理员权限和用户权限下的Z盘Y盘就像是在两个世界,这也就是UAC的功能不是么?隔离,sandbox!
【问题总结】
至此所有问题全部解决。解决方法如下:
使用administrator账户
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\System
的EnableLUA
值改为0,重启即可在管理员权限下打开VS或者其他工具,在文件资源管理器中设置网络磁盘映射即可