How to add an uac shield icon to a MenuItem
Since Windows Vista an application needs administrator privileges to perform some system operations like starting or stopping a Windows service. To gain these privileges you can add an “app.manifest” file to your project in Visual Studio and set the requestedExecutionLevel to requireAdministrator.
In Windows there is always the small shield icon to inform the user that administrator privileges are required for the desired action:
To add this icon to your own context menu in a WinForms project the following steps are required:
1. Check that the user currently has no administrator privileges:
public bool HasAdministratorRights { get { var pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); return pricipal != null && pricipal.IsInRole(WindowsBuiltInRole.Administrator); } }
2. Use a ContextMenuStrip and ToolStripMenuItems instead of the old ContextMenu and MenuItems.
3. Import the SHGetStockIconInfo method from shell32:
private static class NativeMethods { [DllImport("Shell32.dll", SetLastError = false)] public static extern Int32 SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii); public enum SHSTOCKICONID : uint { SIID_SHIELD = 77 } [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 = 260)] public string szPath; } }
4. Fetch the shield icon and create a bitmap out of the HIcon:
private void SetUacShield(ToolStripMenuItem menuItem) { NativeMethods.SHSTOCKICONINFO iconResult = new NativeMethods.SHSTOCKICONINFO(); iconResult.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(iconResult); NativeMethods.SHGetStockIconInfo( NativeMethods.SHSTOCKICONID.SIID_SHIELD, NativeMethods.SHGSI.SHGSI_ICON | NativeMethods.SHGSI.SHGSI_SMALLICON, ref iconResult); menuItem.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText; menuItem.Image = Bitmap.FromHicon(iconResult.hIcon); }
That’s all. Now you can restart you application with administrator rights or call another executable with the “runas” verb:
private void RunAsAdmin(string fileName, string args) { var processInfo = new ProcessStartInfo { Verb = "runas", FileName = fileName, Arguments = args, }; try { Process.Start(processInfo); } catch (Win32Exception) { // Do nothing... } }