.NET中提升UAC权限的方法总结
【题外话】
从Vista开始,由于增加了UAC(用户账户控制,User Account Control)功能,使得管理员用户平时不再拥有能控制所有功能的管理员权限了,所以在调用很多比较重要的功能时需要提升权限来实现。有时候写的程序需要调用这种权限,那么大概就是分为运行前就提升以及运行后再提升两种,在这里整理如下。
【文章索引】
【一、程序运行前提升权限】
如果整个程序都需要使用管理员权限的话(甚至主界面上显示的内容都需要管理员权限才行),那么可以让程序一运行时就提升管理员权限,就如同大部分的安装程序一样。程序运行时提高权限通常采用设置manifest文件的方式,可以在项目中添加“应用程序清单文件”,添加完成后会生成如下图所示的一个文件。除此之外,也可以通过选择项目属性,然后进入“安全性”选项卡,然后选择“启用 ClickOnce 安全设置”后也会在项目的“Properties”目录下生成app.manifest文件。

在注释中很明确的说明了如果要在程序中如果需要更高的权限需要修改哪部分,不过非常好奇,这段注释并没有说明应该修改成哪种方式。
在http://blogs.msdn.com/b/winsdk/archive/2010/05/31/dealing-with-administrator-and-standard-user-s-context.aspx搜索到了这两者的区别,区别如下:
Possible requested execution level values
|
Value |
Description |
Comment |
|
asInvoker |
The application runs with the same access token as the parent process. |
Recommended for standard user applications. Do refractoring with internal elevation points, as per the guidance provided earlier in this document. |
|
highestAvailable |
The application runs with the highest privileges the current user can obtain. |
Recommended for mixed-mode applications. Plan to refractor the application in a future release. |
|
requireAdministrator |
The application runs only for administrators and requires that the application be launched with the full access token of an administrator. |
Recommended for administrator only applications. Internal elevation points are not needed. The application is already running elevated. |
区别即是,highestAvailable按当前账号能获取到的权限执行,而requireAdministrator则是以具有完整权限的管理员运行。如果当前账户是管理员账户的话,那么两者都是可以的通过提升权限来获取到管理员权限的;而如果当前账户是Guest的话,那么highestAvailable则放弃提升权限而直接运行,而requireAdministrator则允许输入其他管理员账户的密码来提升权限。

其中App1使用的是highestAvailable,而App2则使用的是requireAdministrator,可以看出在Administrator用户下都需要提升权限来运行,在关闭UAC的时候都不需要提升权限。而比如在Guest下highestAvailable放弃了提升权限,同时如果使用requireAdministrator的话则会提示类似下图的输入其他管理员账户密码的对话框:

所以,如果一个程序必须要求管理员权限才能执行或者才能执行得有意义(比如主界面上的信息需要管理员权限才能显示之类的),那么不妨设置为requireAdministrator,即使使用Guest登陆的话也需要提升管理员权限;否则也可设置为highestAvaliable。
【二、程序运行后提升权限】
如果程序默认不需要权限就能运行大部分功能,只是在个别功能上需要管理员权限的话,那么可以采用程序运行后,当用户需要提升权限的时候再提升权限重新运行程序。由于权限是按进程来的,所以如果需要提升整个程序的权限,只能以管理员权限创建进程以后再结束本程序,或者以管理员权限运行其他程序或者程序通过不同参数来执行不同功能。以管理员权限执行程序其实非常简单,只要将ProcessStartInfo对象的Verb属性设置为“runas”即可,例如如下的代码即可以管理员权限重启本程序。
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = Application.ExecutablePath;
psi.Verb = "runas"; try
{
Process.Start(psi);
Application.Exit();
}
catch (Exception eee)
{
MessageBox.Show(eee.Message);
}
当然,运行其他程序也是一样的。
除此之外,我们可能还需要在这个按钮或菜单上绘制UAC盾牌的图标,其实系统已经提供了这样的方法。
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, IntPtr lParam);
public const UInt32 BCM_SETSHIELD = 0x160C;
调用的时候只要将按钮的FlatStyle设置为System,然后采用如下的代码就可以了,最后一项如果设为0的话则会取消显示UAC的盾牌图标。
SendMessage(button1.Handle, BCM_SETSHIELD, , (IntPtr));
不过如果要往菜单上或者WPF的Button上绘制UAC盾牌的图标就没法这样去做了,不过好在我们还可以获取到系统图标,不嫌弃的话可以用.NET自带的System.Drawing.SystemIcons.Shield,其实好多软件用的就是这个图标,原图如下(32×32):

当然,也可以通过DllImport的方式从系统中获取系统内置的图标,其中UAC盾牌的图标的ID是77,代码如下。
[DllImport("shell32.dll", SetLastError = false)]
public static extern Int32 SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii);
public enum SHSTOCKICONID : uint
{
SIID_SHIELD =
}
[Flags]
public enum SHGSI : uint
{
SHGSI_ICON = 0x000000100,
SHGSI_SMALLICON = 0x000000001
}
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHSTOCKICONINFO
{
public UInt32 cbSize;
public IntPtr hIcon;
public Int32 iSysIconIndex;
public Int32 iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = )]
public string szPath;
}
然后如下调用就可以将UAC盾牌的图标设置到菜单上了:
SHSTOCKICONINFO iconInfo = new SHSTOCKICONINFO();
iconInfo.cbSize = (UInt32)System.Runtime.InteropServices.Marshal.SizeOf(iconInfo);
SHGetStockIconInfo(SHSTOCKICONID.SIID_SHIELD, SHGSI.SHGSI_ICON | SHGSI.SHGSI_SMALLICON, ref iconInfo);
Icon icon = Icon.FromHandle(iconInfo.hIcon); menu.Image = icon.ToBitmap();
图中menu1是使用的System.Drawing.SystemIcons.Shield,menu2使用的通过shell32.dll获取到的图标,button1是使用的SendMessage直接显示的UAC的图标。

当然,还是应该判断一下系统的版本的,确保系统是Vista及以后的版本,否则就不需要提升权限了。判断是否是Vista只需要判断系统主版本号是否大于等于6就可以了,例如以下的代码。
Boolean afterVista = (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= );
【三、程序中判断当前权限】
如果要判断当前是否以管理员身份运行,只需引用“System.Security.Principal”这个命名空间,然后就可以通过如下的代码获取当前是否以管理员在运行。
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
Boolean isRunasAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
除了获取当前是否是以管理员运行,还可以通过DllImport的方式获取到当前用户是否是管理员用户以及当前进程是否提升了权限(仅限Vista及以上的版本)等等,详情可以见相关链接2中的代码。
【相关链接】
- 编写C#程序让其在Win7 下以管理员权限运行:http://www.cr173.com/html/11557_1.html
- UAC self-elevation (CSUACSelfElevation):http://code.msdn.microsoft.com/windowsdesktop/CSUACSelfElevation-644673d3
- How to add an uac shield icon to a MenuItem:http://www.peschuster.de/2011/12/how-to-add-an-uac-shield-icon-to-a-menuitem/
.NET中提升UAC权限的方法总结的更多相关文章
- android中获取root权限的方法以及原理(转)
一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. 二. Root 的介绍 1. Root 的目的 可以让我们拥有 ...
- centos7中提升用户权限
提升用户权限我看网上资源有两种方法,一种是修改/etc/sudoers/文件将新增的用户权限提升为和root一样的权限,这种方法不知道怎么回事我没用应用成功,这里我介绍第二种方法,第二种方法是更改/e ...
- UAC权限
.NET中提升UAC权限的方法总结 [题外话] 从Vista开始,由于增加了UAC(用户账户控制,User Account Control)功能,使得管理员用户平时不再拥有能控制所有功能的管理员权 ...
- cocoa中获得root权限的几种方法
目前我所知道的,在cocoa中获得root权限的方法有3种: 1. 通过AuthorizationCopyRights函数 2. 在UI上添加一个锁的样子的控件,然后通过开关这个锁来获取root权限 ...
- 实现在vista和win7中使用管理员权限接收WM_DROPFILES(OnDropFiles())消息的方法(好像XP不支持这个函数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #pragma once #ifndef WM_COPYGLOBALD ...
- 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离
在某国外大型汽车公司BI项目中,有一个子项目,需要通过大屏幕展示销售报表,程序需要自动启动和关闭.开发人员在开发过程中,发现在Win7的service中不能直接操作UI进程,调查过程中,发现如 ...
- 利用PATH环境变量 - 提升linux权限~👻
利用PATH提升linux权限 参考地址:https://www.hackingarticles.in/linux-privilege-escalation-using-path-variable/ ...
- mysql 5.7中的用户权限分配相关解读!
这篇文章主要介绍了MySQL中基本的用户和权限管理方法,包括各个权限所能操作的事务以及操作权限的一些常用命令语句,是MySQL入门学习中的基础知识,需要的朋友可以参考下 一.简介 各大帖子及文章都会讲 ...
- iOS开发中的这些权限,你搞懂了吗?
APP开发避免不开系统权限的问题,如何在APP以更加友好的方式向用户展示系统权限,似乎也是开发过程中值得深思的一件事. 那如何提高APP获取iOS系统权限的通过率呢?有以下几种方式:1.在用户打开AP ...
随机推荐
- Spring-boot 开发Web应用
动态修改Freemarker模版: 设置模版属性: spring.freemarker.cache=false 启动应用方式有两种: a. 运行main()函数启动应用:则修改完模版文件后,需要把 ...
- AOJ 0121: Seven Puzzle【BFS】
From: AOJ 0121 思路:与前几题的bfs不同,这次的bfs没有明确的移动对象,看似任意一个数都可以当成对象移动.这时我们只需要抓住一个格子就行,比如我们把0作为移动对象,那么0在地图中漫游 ...
- Jetpack 由 WordPress.com 出品
官网:https://jetpack.com/ Jetpack 由 WordPress.com 出品. Jetpack 通过为您提供访客统计数据和安全服务.加速图像传输以及帮您获得更多浏览量,可以简化 ...
- 【Gson】互相转化
Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库.可以将一个 JSON 字符串转成一个 Java 对象,或者反过来. 对象转为字符串 Strin ...
- 深入理解Java的接口和抽象类(转)
深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...
- 历年NOIP水题泛做
快noip了就乱做一下历年的noip题目咯.. noip2014 飞扬的小鸟 其实这道题并不是很难,但是就有点难搞 听说男神错了一个小时.. 就是$f_{i,j}$表示在第$i$个位置高度为$j$的时 ...
- uva12063数位dp
辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...
- 非交织YUV格式转换
本文为自己写的从非交织yuv420转换出yuv444,yuv422h,yuv422v和手动裁剪422h,422v图片的代码 #include <fcntl.h> #include < ...
- Linux命令dos2unix 从windows转换到linux --- nuix2dos从linux转换到windows
dos2unix命令用来将DOS格式的文本文件转换成UNIX格式的(DOS/MAC to UNIX text file format converter).DOS下的文本文件是以\r\n作为断行标志的 ...
- 印象笔记 剪藏(Evernote WebClipper) bug 记录
问题记录: Chrome版的 webclipper不知为何新装的时候切换到中国版印象笔记登陆的时候闪退,然后之后就无法进入中国区的登录页面:international版确认可以登录. cookies是 ...