在Win7中常會看到某些程式中會有個按鈕,按鈕上會有個盾牌的圖示,按下後能提升存取權限。這邊紀錄一下這樣的功能要怎樣實現。
首先是盾牌的圖示,實作時不是自己去換按鈕的圖片,而是要對Button發送BCM_SETSHIELD(0x0000160C)的Message,訊息發送時lParam參數帶1或0去決定是否顯示盾牌圖示。這邊需注意的是因為這功能在vista以前不提供,所以必須做些處理,另外則是這功能必須要將按鈕的FlatStyle設為System,運行後才會有效果。
02 | const int BCM_SETSHIELD = 0x0000160C; |
07 | private static bool AtLeastVista() |
09 | return (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6); |
12 | private static void SetButtonShield(Button btn, bool showShield) |
17 | btn.FlatStyle = FlatStyle.System; |
18 | SendMessage( new HandleRef(btn, btn.Handle), BCM_SETSHIELD, IntPtr.Zero, showShield ? new IntPtr(1) : IntPtr.Zero); |
提升權限的部分則是透過Process去實現RunAs功能,比較要注意的是要帶入當下執行檔的位置,並將Verb設為runas。
1 | ProcessStartInfo psi = new ProcessStartInfo |
3 | Arguments = "-justelevated" , |
5 | ErrorDialogParentHandle = form.Handle, |
6 | FileName = Application.ExecutablePath, |
這邊筆者方便後續使用,將其整理為擴充方法。
02 | using System.Collections.Generic; |
05 | using System.Windows.Forms; |
06 | using System.Runtime.InteropServices; |
07 | using System.Diagnostics; |
09 | public static class ButtonExtension |
12 | [DllImport( "shell32.dll" , EntryPoint = "#680" , CharSet = CharSet.Unicode)] |
13 | private static extern bool IsUserAnAdmin(); |
15 | [DllImport( "user32.dll" , CharSet = CharSet.Unicode)] |
16 | private static extern IntPtr SendMessage(HandleRef hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); |
21 | const int BCM_SETSHIELD = 0x0000160C; |
25 | #region Private Method |
26 | private static bool AtLeastVista() |
28 | return (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6); |
31 | private static void SetButtonShield(Button btn, bool showShield) |
36 | btn.FlatStyle = FlatStyle.System; |
37 | SendMessage( new HandleRef(btn, btn.Handle), BCM_SETSHIELD, IntPtr.Zero, showShield ? new IntPtr(1) : IntPtr.Zero); |
40 | private static Form GetWindowForm(Control control) |
42 | Control parent = control.Parent; |
48 | return parent as Form; |
50 | return GetWindowForm(parent); |
56 | public static void EnableShieldIcon( this Button button) |
58 | SetButtonShield(button, true ); |
61 | public static void EnableRunAsProcess( this Button button) |
63 | button.Click -= new EventHandler(button_RunAsProcess); |
64 | button.Click += new EventHandler(button_RunAsProcess); |
70 | private static void button_RunAsProcess( object sender, EventArgs e) |
72 | Button button = sender as Button; |
73 | Form form = GetWindowForm(button); |
78 | ProcessStartInfo psi = new ProcessStartInfo |
80 | Arguments = "-justelevated" , |
82 | ErrorDialogParentHandle = form.Handle, |
83 | FileName = Application.ExecutablePath, |
93 | MessageBox.Show(ex.Message); |
使用時對Button去設定EnableShieldIcon與EnableRunAsProcess就可以了。
1 | private void Form1_Load( object sender, EventArgs e) |
3 | button1.EnableShieldIcon(); |
4 | button1.EnableRunAsProcess(); |
運行後就會看到盾牌圖示,點擊按鈕也會將權限提升。
![image](http://files.dotblogs.com.tw/larrynung/1111/CEnableUACShieldiconsandrunasadministrat_BB8B/image_thumb.png)