前几天在园子里看到一些关于UAC的文章。我觉得应用程序应该在不减少功能的情况下尽量减少需要管理员权限的操作,即使需要管理员权限来进行某些操作也不要一启动就提示要管理员权限~这样既没有让用户清楚的知道你拿管理员权限做了些什么又可能导致管理员权限被滥用。本文演示的是在 WinForm 和 WPF 应用程序中点击按钮才弹出 UAC 提示要求管理员权限,这样即使用户不提供管理员权限,我们的应用程序仍然可以完成其他普通权限操作。Windows Vista 中有很多地方都是这样,如打开计算机属性(开始 | 右键计算机 | 属性)是不需要管理员权限的,但从这里点击“设备管理器”或“系统保护”等设置就会弹出 UAC 提示,并且这些按钮前会有一个小盾牌。
先演示在 WinForm 中实现上述功能,以下是关键代码,完整代码在文后提供下载
1// DllImport 以使用 Win32 API
2 [DllImport("user32")]
3 public static extern UInt32 SendMessage(IntPtr hWnd, UInt32 msg, UInt32 wParam, UInt32 lParam);
4
5 /// <summary>
6 /// 构造器
7 /// </summary>
8 public Form1()
9 {
10 InitializeComponent();
11
12 // 当程序没有以管理员权限启动时
13 if (!IsAdmin())
14 {
15 button1.FlatStyle = FlatStyle.System;
16 SendMessage(button1.Handle, 0x160C, 0, 0xFFFFFFFF); // 向按钮发送消息使之加上 UAC 盾牌标志
17 }
18 }
19
20 /// <summary>
21 /// 判断当前是否具有管理员权限
22 /// </summary>
23 private bool IsAdmin()
24 {
25 return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
26 }
27
28 // 需要管理员权限操作的按钮
29 private void button1_Click(object sender, EventArgs e)
30 {
31 // 将需要管理员权限的操作单独写成一个应用程序在此启动或以管理员权限重新启动当前应用程序
32 // 这里演示的是以管理员权限启动另一个应用程序
33 ProcessStartInfo start = new ProcessStartInfo();
34 start.WorkingDirectory = Environment.CurrentDirectory;
35 start.FileName = "UacValidation.exe"; // 需要以管理员权限启动的文件
36 start.Verb = "runas"; // 这个动词将弹出 UAC 提示
37 try
38 {
39 Process p = Process.Start(start);
40 }
41 catch (System.ComponentModel.Win32Exception ex)
42 {
43 // 如用户在 UAC 提示中点击取消,也就是获取管理员权限失败后的处理
44 MessageBox.Show("未获得管理员权限", "操作失败");
45 }
46 }
2 [DllImport("user32")]
3 public static extern UInt32 SendMessage(IntPtr hWnd, UInt32 msg, UInt32 wParam, UInt32 lParam);
4
5 /// <summary>
6 /// 构造器
7 /// </summary>
8 public Form1()
9 {
10 InitializeComponent();
11
12 // 当程序没有以管理员权限启动时
13 if (!IsAdmin())
14 {
15 button1.FlatStyle = FlatStyle.System;
16 SendMessage(button1.Handle, 0x160C, 0, 0xFFFFFFFF); // 向按钮发送消息使之加上 UAC 盾牌标志
17 }
18 }
19
20 /// <summary>
21 /// 判断当前是否具有管理员权限
22 /// </summary>
23 private bool IsAdmin()
24 {
25 return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
26 }
27
28 // 需要管理员权限操作的按钮
29 private void button1_Click(object sender, EventArgs e)
30 {
31 // 将需要管理员权限的操作单独写成一个应用程序在此启动或以管理员权限重新启动当前应用程序
32 // 这里演示的是以管理员权限启动另一个应用程序
33 ProcessStartInfo start = new ProcessStartInfo();
34 start.WorkingDirectory = Environment.CurrentDirectory;
35 start.FileName = "UacValidation.exe"; // 需要以管理员权限启动的文件
36 start.Verb = "runas"; // 这个动词将弹出 UAC 提示
37 try
38 {
39 Process p = Process.Start(start);
40 }
41 catch (System.ComponentModel.Win32Exception ex)
42 {
43 // 如用户在 UAC 提示中点击取消,也就是获取管理员权限失败后的处理
44 MessageBox.Show("未获得管理员权限", "操作失败");
45 }
46 }
下面演示的是在 WPF 应用程序中完成上述功能的关键代码
1/// <summary>
2 /// 构造器
3 /// </summary>
4 public Window1()
5 {
6 InitializeComponent();
7
8 // 当应用程序没有以管理员权限运行时按钮显示盾牌
9 if (!IsAdmin())
10 {
11 // 由于在 WPF 中控件没有Handle,所以需要绘图实现
12 // 先取出盾牌图标
13 Icon icon = new Icon(SystemIcons.Shield, 12, 12);
14 // 绘图
15 Bitmap bitmap = Bitmap.FromHicon(icon.Handle);
16 // 使之显示到界面
17 MemoryStream stream = new MemoryStream();
18 bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
19 ImageBrush imageBrush = new ImageBrush();
20 ImageSourceConverter imageSourceConverter = new ImageSourceConverter();
21 image1.Margin = new Thickness(0, 0, 5, 0);
22 image1.Width = 15;
23 image1.Source = (ImageSource)imageSourceConverter.ConvertFrom(stream);
24 }
25 }
26
27 /// <summary>
28 /// 判断当前是否具有管理员权限
29 /// </summary>
30 private bool IsAdmin()
31 {
32 return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
33 }
34
35 // 需要管理员权限操作的按钮
36 private void button1_Click(object sender, RoutedEventArgs e)
37 {
38 // 将需要管理员权限的操作单独写成一个应用程序在此启动或以管理员权限重新启动当前应用程序
39 // 这里演示的是以管理员权限启动另一个应用程序
40 ProcessStartInfo start = new ProcessStartInfo();
41 start.WorkingDirectory = Environment.CurrentDirectory;
42 start.FileName = "UacValidation.exe"; // 需要以管理员权限启动的文件
43 start.Verb = "runas"; // 这个动词将弹出 UAC 提示
44 try
45 {
46 Process p = Process.Start(start);
47 }
48 catch (System.ComponentModel.Win32Exception ex)
49 {
50 MessageBox.Show("未获得管理员权限","操作失败");
51 }
52 }
2 /// 构造器
3 /// </summary>
4 public Window1()
5 {
6 InitializeComponent();
7
8 // 当应用程序没有以管理员权限运行时按钮显示盾牌
9 if (!IsAdmin())
10 {
11 // 由于在 WPF 中控件没有Handle,所以需要绘图实现
12 // 先取出盾牌图标
13 Icon icon = new Icon(SystemIcons.Shield, 12, 12);
14 // 绘图
15 Bitmap bitmap = Bitmap.FromHicon(icon.Handle);
16 // 使之显示到界面
17 MemoryStream stream = new MemoryStream();
18 bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
19 ImageBrush imageBrush = new ImageBrush();
20 ImageSourceConverter imageSourceConverter = new ImageSourceConverter();
21 image1.Margin = new Thickness(0, 0, 5, 0);
22 image1.Width = 15;
23 image1.Source = (ImageSource)imageSourceConverter.ConvertFrom(stream);
24 }
25 }
26
27 /// <summary>
28 /// 判断当前是否具有管理员权限
29 /// </summary>
30 private bool IsAdmin()
31 {
32 return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
33 }
34
35 // 需要管理员权限操作的按钮
36 private void button1_Click(object sender, RoutedEventArgs e)
37 {
38 // 将需要管理员权限的操作单独写成一个应用程序在此启动或以管理员权限重新启动当前应用程序
39 // 这里演示的是以管理员权限启动另一个应用程序
40 ProcessStartInfo start = new ProcessStartInfo();
41 start.WorkingDirectory = Environment.CurrentDirectory;
42 start.FileName = "UacValidation.exe"; // 需要以管理员权限启动的文件
43 start.Verb = "runas"; // 这个动词将弹出 UAC 提示
44 try
45 {
46 Process p = Process.Start(start);
47 }
48 catch (System.ComponentModel.Win32Exception ex)
49 {
50 MessageBox.Show("未获得管理员权限","操作失败");
51 }
52 }