【题外话】

从Vista开始,由于增加了UAC(用户账户控制,User Account Control)功能,使得管理员用户平时不再拥有能控制所有功能的管理员权限了,所以在调用很多比较重要的功能时需要提升权限来实现。有时候写的程序需要调用这种权限,那么大概就是分为运行前就提升以及运行后再提升两种,在这里整理如下。

【文章索引】

  1. 程序运行前提升权限
  2. 程序运行后提升权限
  3. 程序中判断当前权限

【一、程序运行前提升权限】

如果整个程序都需要使用管理员权限的话(甚至主界面上显示的内容都需要管理员权限才行),那么可以让程序一运行时就提升管理员权限,就如同大部分的安装程序一样。程序运行时提高权限通常采用设置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中的代码。

【相关链接】

  1. 编写C#程序让其在Win7 下以管理员权限运行:http://www.cr173.com/html/11557_1.html
  2. UAC self-elevation (CSUACSelfElevation):http://code.msdn.microsoft.com/windowsdesktop/CSUACSelfElevation-644673d3
  3. 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权限的方法总结的更多相关文章

  1. android中获取root权限的方法以及原理(转)

    一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. 二. Root 的介绍 1. Root 的目的 可以让我们拥有 ...

  2. centos7中提升用户权限

    提升用户权限我看网上资源有两种方法,一种是修改/etc/sudoers/文件将新增的用户权限提升为和root一样的权限,这种方法不知道怎么回事我没用应用成功,这里我介绍第二种方法,第二种方法是更改/e ...

  3. UAC权限

    .NET中提升UAC权限的方法总结   [题外话] 从Vista开始,由于增加了UAC(用户账户控制,User Account Control)功能,使得管理员用户平时不再拥有能控制所有功能的管理员权 ...

  4. cocoa中获得root权限的几种方法

    目前我所知道的,在cocoa中获得root权限的方法有3种: 1. 通过AuthorizationCopyRights函数 2. 在UI上添加一个锁的样子的控件,然后通过开关这个锁来获取root权限 ...

  5. 实现在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 ...

  6. 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离

        在某国外大型汽车公司BI项目中,有一个子项目,需要通过大屏幕展示销售报表,程序需要自动启动和关闭.开发人员在开发过程中,发现在Win7的service中不能直接操作UI进程,调查过程中,发现如 ...

  7. 利用PATH环境变量 - 提升linux权限~👻

    利用PATH提升linux权限 参考地址:https://www.hackingarticles.in/linux-privilege-escalation-using-path-variable/ ...

  8. mysql 5.7中的用户权限分配相关解读!

    这篇文章主要介绍了MySQL中基本的用户和权限管理方法,包括各个权限所能操作的事务以及操作权限的一些常用命令语句,是MySQL入门学习中的基础知识,需要的朋友可以参考下 一.简介 各大帖子及文章都会讲 ...

  9. iOS开发中的这些权限,你搞懂了吗?

    APP开发避免不开系统权限的问题,如何在APP以更加友好的方式向用户展示系统权限,似乎也是开发过程中值得深思的一件事. 那如何提高APP获取iOS系统权限的通过率呢?有以下几种方式:1.在用户打开AP ...

随机推荐

  1. TDD学习笔记【二】---单元测试简介

    大纲 Testing 的第一个切入点:单元测试. 本篇文章将针对单元测试进行简介,主要内容包含了5W: Why What Where Who When 而How 的部分,属于实现部分,将于下一篇文章介 ...

  2. C语言的一些小知识

    注:本文讨论的"C语言"为GNU C,而非ANSI C 标准库 语法 switch语句中的case关键词可以放在任何地方 switch (a) { case 1:; if (b== ...

  3. NXP恩智浦P89V51RB2/RC2/RD2单片机解密芯片破解方法!

    NXP恩智浦P89V51RB2/RC2/RD2单片机解密芯片破解 P89V51RB2/RC2/RD2是一款80C51微控制器,包含16/32/64kB Flash和1024字节的数据RAM. P89V ...

  4. Java EE之servlet处理表单提交的请求

    1.在源包下新建一个Servlet页,取名为LoginServlet: package weinidingServlet;                            //该Servlet所 ...

  5. Delphi的三目运算 ifthen 和iif

    system.Math和system.StrUtils都有IfThen方法, 返回字符串和 返回 数值型 system.Math.IfThen(vehicle.MILE=0,0,StrToFloat( ...

  6. Attention:本博客暂停更新

    Attention:本博客暂停更新 2016年11月17日08:33:09 博主遗产 http://www.cnblogs.com/radiumlrb/p/6033107.html Dans cett ...

  7. 洛谷 P1378 油滴扩展 Label:搜索

    题目描述 在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界.必须等一个油滴扩展完毕才能放置下一个油滴. ...

  8. 关于DOM对象与JQuery对象的那些事

    这个问题源自上一次的工作室讨论班,主题是"jQuery选择器的使用",在讨论班的结尾,我留了一个思考题:  jQuery获取到的对象和直接调用原生Javascript方法获得的对象 ...

  9. Java 语句循环

    编写程序,显示Welcome to Java 五次. public class Welcome{ public static void main(String[] args){ int i;(定义变量 ...

  10. C语言中函数声明实现的位置

    在学习C语言的时候我遇到了这么个事情,因为之前先学习的C#,在C#编译器中,函数的声明位置不会影响编译的结果,但是在C语言中却发生了错误 先看一段代码: #include <stdio.h> ...