 |
|
|
 |
|
 |
awesome airticle helped alot... but how to remove the icon if i want to? ... i have a situation whr user have to select drives from a drop down list, if the drive is C then put the icon on the button if its not C then remove it.. how can i remove it? 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Instead of calling WindowsIdentity.GetCurrent and returning a boolean for the users built-in role, There is a much easier and simpler way of determinating if the user is an admin using one line of code:
Declare Function IsUserAnAdmin Lib "shell32" () As Boolean
Example:
If IsUserAnAdmin = false then 'Not Admin ElseIf IsUserAnAdmin = True then 'User is admin End If
Its compatible with all versions of windows and greatly simplifies checking if the current user belongs to the administrator group
Steven
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
I just made a translation to VB2008. Here it goes:
Make a new form with one button on it and paste in this code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load If VistaSecurity.IsAdmin Then Button1.Text = "Already admin" Else Button1.Text = "Restart as admin" VistaSecurity.AddShieldToButton(Button1) End If End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click VistaSecurity.RestartElevated() End Sub
Make a new module called VistaSecurity and paste in this code:
Imports System.Security.Principal
Module VistaSecurity
'Declare API Private Declare Ansi Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer Private Const BCM_FIRST As Int32 = &H1600 Private Const BCM_SETSHIELD As Int32 = (BCM_FIRST + &HC)
Public Function IsVistaOrHigher() As Boolean Return Environment.OSVersion.Version.Major < 6 End Function
' Checks if the process is elevated Public Function IsAdmin() As Boolean Dim id As WindowsIdentity = WindowsIdentity.GetCurrent() Dim p As WindowsPrincipal = New WindowsPrincipal(id) Return p.IsInRole(WindowsBuiltInRole.Administrator) End Function
' Add a shield icon to a button Public Sub AddShieldToButton(ByRef b As Button) b.FlatStyle = FlatStyle.System SendMessage(b.Handle, BCM_SETSHIELD, 0, &HFFFFFFFF) End Sub
' Restart the current process with administrator credentials Public Sub RestartElevated() Dim startInfo As ProcessStartInfo = New ProcessStartInfo() startInfo.UseShellExecute = True startInfo.WorkingDirectory = Environment.CurrentDirectory startInfo.FileName = Application.ExecutablePath startInfo.Verb = "runas" Try Dim p As Process = Process.Start(startInfo) Catch ex As Exception Return 'If cancelled, do nothing End Try Application.Exit() End Sub
End Module
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Ok so code is free without limitation... blah blah blah... that's why i pasted it here lol..
Usage: well i say this in the code comments... just add it to a project or assembly... use toolbox... drag the shield-button onto your form.
Note: if your admin, you won't see the shield icon... i assume this is the way this is supposed to work so let me know if shield should always be shown.
So ya... hook onto the Click event with stuff you want an admin to do... it'll take care of the UAC escalation...
using System; using System.ComponentModel; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; using System.Windows.Forms;
namespace StudioControls.Controls { /// <summary> /// Makes a button that shows a shield if its application is run without admin privileges. /// /// This control also calls up a UAC privilege escalation prompt when clicked, which is what the user expects when clicking such a "Shield" button. /// </summary> /// <example> /// Just drop this button in your form, and bind actions to its click event that you know would require admin privileges. /// If the user is an admin, there will be no shield icon, or prompt. /// /// If you want to hide the button from an admins view, like you just want to get admin privileges, then you don't need to hook onto the click event. /// Just check with this controls public static member "IsAdmin()" and make this control not visible if true. /// /// The OnClick event will trigger a UAC escalation attempt where if the user obtains admin privileges, that the program will restart. Then the second time /// the program is loaded, with admin privileges, then whatever is bound to the Click event will get called. /// /// Some things to watch for: /// 1. if the user gets admin priviliges, the program will restart... so your program might require saving and restoring of program state. /// You can listen for this in general by hooking onto this event "Application.ApplicationExit += ..." /// /// However, their is no way to differentiate between UAC starting the application shutdown/restart, and a normal shutdown, so i included additional events: /// EscalationStarting /// EscalationCancelled /// EscalationProgramRestart /// /// 2. When your program restarts, make sure you preserve your programs StartPosition, else it might look sloppy if it suddenly moves from where it appears in the greyed out UAC background... but then again... the taskmanager doesn't care about its StartPosition when you press "Show processes from all users" and it restarts lol. For me i just use StartPosition = CenterScreen for the affected forms. /// </example> /// <remarks> /// Reference: /// http://www.codeproject.com/KB/vista-security/UAC_Shield_for_Elevation.aspx, /// http://buildingsecurecode.blogspot.com/2007/06/how-to-display-uac-shield-icon-inside.html /// </remarks> public class StudioShieldButton : Button { #region Properties
#region FlatStyle Appearance Property
/// <summary> /// Determines the appearance of the control when a user moves the mouse the mouse over the control and clicks. /// </summary> [ Category("Appearance"), Description("Determines the appearance of the control when a user moves the mouse the mouse over the control and clicks."), DefaultValue(typeof(FlatStyle), "System"), ReadOnly(true), Browsable(false) ] public new FlatStyle FlatStyle { get { return base.FlatStyle; } }
#endregion
#endregion
#region DllImports
private const uint BCM_SETSHIELD = 0x0000160C;
[DllImport("user32.dll")] private static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
#endregion
#region Constructor
public StudioShieldButton() { base.FlatStyle = FlatStyle.System; // This must be FlatStyle.System for the shield to work // I also locked the FlatStyle property: // DefaultValue(typeof(FlatStyle), "System"), // ReadOnly(true), // Browsable(false) // so hopefully vs.net won't try to serialize it.
if (!HasAdminPrivileges()) // then show the shield on the button { // Send the BCM_SETSHIELD message to the button control SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(1)); } }
#endregion
#region Members
public static bool HasAdminPrivileges() { WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); WindowsPrincipal windowsPrincipal = new WindowsPrincipal(windowsIdentity); return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator); }
private void AttemptPrivilegeEscalation() { if (HasAdminPrivileges()) throw new SecurityException("Already have administrator privileges.");
ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.UseShellExecute = true; startInfo.WorkingDirectory = Environment.CurrentDirectory; startInfo.FileName = Application.ExecutablePath; startInfo.Verb = "runas"; // will bring up the UAC run-as menu when this ProcessStartInfo is used
#region OnUACEscalationStarting
if (UACEscalationStarting != null) { UACEscalationStarting(this, new EventArgs()); }
#endregion
try { Process.Start(startInfo); } catch (System.ComponentModel.Win32Exception) //occurs when the user has clicked Cancel on the UAC prompt. { #region OnUACEscalationCancelled
if (UACEscalationCancelled != null) { UACEscalationCancelled(this, new EventArgs()); }
#endregion
return; // By returning, we are ignoring the user tried to get UAC priviliges but then hit cancel at the Run-As prompt. } // If we get here, the user successfully got admin powers (for another instance of this program), // so close this low-priviliged instance of the program.
#region OnUACEscalationAndProgramRestart
if (UACEscalationAndProgramRestart != null) { UACEscalationAndProgramRestart(this, new EventArgs()); }
#endregion
Application.Exit(); } #endregion
#region Overrided Members
protected override void OnClick(EventArgs e) { if(HasAdminPrivileges()) // this can only be called if we're an admin. base.OnClick(e);
//Their doesn't seem to be a way to achieve admin privileges without a restart, so the only other option is //assume the user is seeking admin privileges and help them try to.
else AttemptPrivilegeEscalation(); }
#endregion
#region Events
#region UACEscalationStarting Action
[Category("Action")] [Description("This is your last chance to save your programs state, because there’s a good chance a program restart will occur, but only if the user successfully achieves admin privileges with the UAC prompt.")] public event EventHandler UACEscalationStarting;
#endregion
#region UACEscalationCancelled Action
[Category("Action")] [Description("The user cancelled the UAC privilege escalation prompt. There will be no program restart.")] public event EventHandler UACEscalationCancelled;
#endregion
#region UACEscalationAndProgramRestart Action
[Category("Action")] [Description("The user was successful in getting admin privileges so now this application will exit, and just previously a new instance was started.")] public event EventHandler UACEscalationAndProgramRestart;
#endregion
#endregion } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
I tweaked it out with a ton of features:
using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing.Design; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; using System.Windows.Forms; using System.Windows.Forms.Design;
namespace StudioControls.Controls { /// <summary> /// Makes a button that shows a shield if its application is run without admin privileges. /// /// This control also calls up a UAC privilege escalation prompt when clicked, which is what the user expects when clicking such a "Shield" button. /// /// This control can be configured to restart the current application with admin privileges, or start a new application with admin priileges, /// pending UAC privilege escalation login. Just set the EscalationGoal property to do this. /// /// But for anything other then achieving admin privileges, but requires admin privileges, hook the Click event and put what you want /// there. Only an admin will be able to enter your event. /// </summary> /// <example> /// Just drop this button in your form, and bind actions to its click event that you know would require admin privileges. /// If the user is an admin, there will be no shield icon, or prompt. /// /// NOTE: if the CURRENT program requires admin privileges, then it must be restarted... but the default behavior is to start a DIFFERANT /// appliction with admin privileges so set the EscalationGoal property accordingly. /// /// If you want to hide the button from an admins view, like you just want to get admin privileges with this button, then just check with this /// controls public static member "IsAdmin()" and make this control not visible if true. /// /// Some things to watch for: /// /// 0. AlwaysShowShield property for your enjoyment. /// /// 1. Not all UAC privilege escalation requires a program restart, for example in "programs and features", the "turn windows features on or off" /// feature opens a new application without closing the one which spawned it. /// /// Use the following property to specify loading a new process: /// EscalationCustomProcessPath //leave it default = "" and it'll load Application.ExecutablePath. /// /// 2. if the user gets admin priviliges, and this controls EscalationGoal = EscalationGoal.RestartThisApplication, /// the program will restart... so your program might require saving and restoring of program state. /// You can listen for this in general by hooking onto this event "Application.ApplicationExit += ..." /// However, their is no way to differentiate between UAC starting the application shutdown/restart, and a normal shutdown, so i included /// additional events: /// EscalationStarting /// EscalationCancelled /// EscalationSuccessful /// /// Note: if EscalationGoal = EscalationGoal.StartAnotherApplication then this program will not exit. /// /// 3. When your program restarts, make sure you preserve your programs StartPosition, else it might look sloppy if it suddenly moves from where it /// appears in the greyed out UAC background... but then again... the taskmanager doesn't care about its StartPosition when you press /// "Show processes from all users" and it restarts lol. For me i just use StartPosition = CenterScreen for the affected forms. /// </example> /// <remarks> /// Reference: /// http://www.codeproject.com/KB/vista-security/UAC_Shield_for_Elevation.aspx, /// http://buildingsecurecode.blogspot.com/2007/06/how-to-display-uac-shield-icon-inside.html /// </remarks> public class StudioShieldButton : Button { #region Fields
public delegate void EscalationHandler(EscalationGoal escalationGoal, object sender, EventArgs e);
#endregion
#region Properties
#region FlatStyle Appearance Property
/// <summary> /// Determines the appearance of the control when a user moves the mouse the mouse over the control and clicks. /// </summary> [ Category("Appearance"), Description("Determines the appearance of the control when a user moves the mouse the mouse over the control and clicks."), DefaultValue(typeof(FlatStyle), "System"), ReadOnly(true), Browsable(false) ] public new FlatStyle FlatStyle { get { return base.FlatStyle; } }
#endregion
#region AlwaysShowShield Appearance Property
private bool alwaysShowShield = false; /// <summary> /// Gets or sets if the shield icon should always be visible. /// </summary> [ Category("Appearance"), Description("Gets or sets if the shield icon should always be visible."), DefaultValue(typeof(bool), "false"), ] public bool AlwaysShowShield { get { return alwaysShowShield; } set { alwaysShowShield = value;
if (!HasAdminPrivileges() || alwaysShowShield) // then show the shield on the button { // Show the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(1)); // the (1) for true } else { // Hide the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(0)); // the (0) for false } } }
#region Serialization /// <summary> /// Should serialize AlwaysShowShield property. /// </summary> /// <returns>True if should serialize, else false.</returns> private bool ShouldSerializeAlwaysShowShield() { //Only serialize nondefault values return (alwaysShowShield != false); } /// <summary> /// Resets AlwaysShowShield property. /// </summary> private void ResetAlwaysShowShield() { alwaysShowShield = false;
if (HasAdminPrivileges()) // then show the shield on the button { // Show the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(1)); // the (1) for true }
else { // Hide the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(0)); // the (0) for false } } #endregion
#endregion
#region EscalationGoal Behavior Property
private EscalationGoal escalationGoal = EscalationGoal.StartAnotherApplication; /// <summary> /// Gets or sets the EscalationGoal for this UAC "shield" button. /// </summary> [ Category("Behavior"), Description("Gets or sets the EscalationGoal for this UAC \"shield\" button."), DefaultValue(typeof(EscalationGoal), "StartAnotherApplication") ] public EscalationGoal EscalationGoal { get { return escalationGoal; } set { escalationGoal = value; } }
#region Serialization /// <summary> /// Should serialize EscalationGoal property. /// </summary> /// <returns>True if should serialize, else false.</returns> private bool ShouldSerializeEscalationGoal() { //Only serialize nondefault values return (escalationGoal != EscalationGoal.StartAnotherApplication); } /// <summary> /// Resets EscalationGoal property. /// </summary> private void ResetEscalationGoal() { escalationGoal = EscalationGoal.StartAnotherApplication; } #endregion
#endregion
#region EscalationCustomProcessPath Behavior Property
private string escalationCustomProcessPath = String.Empty; /// <summary> /// Gets or sets the path to the application that this program starts when hit. /// Leave it \"\" to load the current Application.ExecutablePath. /// </summary> [ Category("Behavior"), Description("Gets or sets the path to the application that this program starts when hit. Leave it \"\" to load the current Application.ExecutablePath."), DefaultValue(typeof(string), "\"\""), Editor(typeof(FilteredFileNameEditor /*FileNameEditor*/), typeof(UITypeEditor)) ] public string EscalationCustomProcessPath { get { return escalationCustomProcessPath; } set { escalationCustomProcessPath = value; } }
#region Serialization /// <summary> /// Should serialize EscalationCustomProcessPath property. /// </summary> /// <returns>True if should serialize, else false.</returns> private bool ShouldSerializeEscalationCustomProcessPath() { //Only serialize nondefault values return (escalationCustomProcessPath != String.Empty); } /// <summary> /// Resets EscalationCustomProcessPath property. /// </summary> private void ResetEscalationCustomProcessPath() { escalationCustomProcessPath = String.Empty; } #endregion
#endregion
#endregion
#region DllImports
private const uint BCM_SETSHIELD = 0x0000160C;
[DllImport("user32.dll")] private static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
#endregion
#region Constructor
public StudioShieldButton() { base.FlatStyle = FlatStyle.System; // This must be FlatStyle.System for the shield to work // I also locked the FlatStyle property: // DefaultValue(typeof(FlatStyle), "System"), // ReadOnly(true), // Browsable(false) // so hopefully vs.net won't try to serialize it.
AlwaysShowShield = alwaysShowShield; //i'm forcing the code in the Set{} of "AlwaysShowShield" to run. }
#endregion
#region Members
public static bool HasAdminPrivileges() { WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); WindowsPrincipal windowsPrincipal = new WindowsPrincipal(windowsIdentity); return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator); }
private ProcessStartInfo EscalationCustomProcessStartInfo() { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.UseShellExecute = true; startInfo.FileName = (escalationCustomProcessPath == String.Empty) ? Application.ExecutablePath : escalationCustomProcessPath; startInfo.Verb = "runas"; // will bring up the UAC run-as menu when this ProcessStartInfo is used
return startInfo; }
private void AttemptPrivilegeEscalation() { if (HasAdminPrivileges()) throw new SecurityException("Already have administrator privileges.");
ProcessStartInfo startInfo = EscalationCustomProcessStartInfo();
OnEscalationStarting(escalationGoal, this, new EventArgs());
try { Process.Start(startInfo); }
catch (System.ComponentModel.Win32Exception) //occurs when the user has clicked Cancel on the UAC prompt. { OnEscalationCancelled(escalationGoal, this, new EventArgs()); return; // By returning, we are ignoring the user tried to get UAC priviliges but then hit cancel at the "Run-As" prompt. }
OnEscalationSuccessful(escalationGoal, this, new EventArgs());
if (escalationGoal == EscalationGoal.RestartThisApplication) // so at this point the program would of already been restarted Application.Exit(); }
private void OnEscalationStarting(EscalationGoal escalationGoal, object sender, EventArgs e) { if (EscalationStarting != null) { EscalationStarting(escalationGoal, sender, e); } }
private void OnEscalationCancelled(EscalationGoal escalationGoal, object sender, EventArgs e) { if (EscalationCancelled != null) { EscalationCancelled(escalationGoal, sender, e); } }
private void OnEscalationSuccessful(EscalationGoal escalationGoal, object sender, EventArgs e) { if (EscalationSuccessful != null) { EscalationSuccessful(escalationGoal, sender, e); } }
#endregion
#region Overrided Members
protected override void OnClick(EventArgs e) { if (HasAdminPrivileges()) // this can only be called if we're an admin, else we get security exceptions. { if(escalationGoal == EscalationGoal.RestartThisApplication) // if the button was intended to restart this app for the sake of getting admin power, well we got admin power now so do the click event. base.OnClick(e);
else if (escalationGoal == EscalationGoal.StartAnotherApplication) { ProcessStartInfo startInfo = EscalationCustomProcessStartInfo();
//todo: slight issue with this... when the program is in admin status... //if my EscalationCustomProcessPath is set to some random program that goes online right away //i get norton saying this application program (not the other program) is trying to connect to the internet...
try { Process.Start(startInfo); }
catch (System.ComponentModel.Win32Exception) //occurs when the user has clicked Cancel on some "Open File - Security Warning" form. { } } }
else AttemptPrivilegeEscalation(); }
#endregion
#region Events
#region EscalationStarting Action
[Category("Action")] [Description("A UAC privilege escalation is going to start next.")] public event EscalationHandler EscalationStarting;
#endregion
#region EscalationCancelled Action
[Category("Action")] [Description("The user cancelled the UAC privilege escalation prompt.")] public event EscalationHandler EscalationCancelled;
#endregion
#region EscalationSuccessful Action
[Category("Action")] [Description("The user was successful in getting admin privileges.")] public event EscalationHandler EscalationSuccessful;
#endregion
#endregion }
public enum EscalationGoal { RestartThisApplication, StartAnotherApplication }
//http://72.14.205.104/search?q=cache:2HrHWneYMSAJ:forums.microsoft.com/MSDN/ShowPost.aspx%3FPostID%3D66703%26SiteID%3D1+UITypeEditor+directory+path+Editor+property&hl=en&ct=clnk&cd=2&gl=us internal class FilteredFileNameEditor : UITypeEditor { private OpenFileDialog ofd = new OpenFileDialog();
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { ofd.FileName = value.ToString(); ofd.Filter = "Programs|*.exe|All Files|*.*"; //ofd.Filter = "Programs|*.exe;*.pif,*.com;*.bat;*.cmd|All Files|*.*"; //ofd.Filter = "Text File|*.txt|All Files|*.*"; if (ofd.ShowDialog() == DialogResult.OK) { return ofd.FileName; } return base.EditValue(context, provider, value); } } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I found many problems with it while refactoring... so that's all fixed.
http://wolfsfiles.googlepages.com/StudioShieldButton.cs[^]
if link is dead, here's a pasted copy:
using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing.Design; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; using System.Windows.Forms; using System.Windows.Forms.Design; using System.IO;
namespace StudioControls.Controls { /// <summary> /// Makes a button that shows a shield if its application is run without admin privileges. /// /// This control can be used to restart the current application with admin, or start another with admin. /// /// Place code in a subscribed Click event that you only want executed by administrators. /// The reason is, you can use the button to both obtain admin power via UAC, and when the program restarts /// it'll loose the shield icon (but theirs a option to still show it), and then whatever code you wanted /// to be executed in the click event --- for admin only --- can now be executed in the priviliged app. /// </summary> /// <example> /// Some things to watch for: /// /// 0. AlwaysShowShield property for your enjoyment. /// /// 1. Not all UAC privilege escalation requires a program restart, for example in "programs and features", the "turn windows features on or off" /// feature opens a new application without closing the one which spawned it. /// /// Use the following properties to specify loading a new process: /// /// EscalationCustomProcessPath = string path to a .exe, etc /// EscalationGoal = EscalationGoal.StartAnotherApplication; /// /// 2. if the user gets admin priviliges, and this controls EscalationGoal = EscalationGoal.RestartThisApplication, /// the program will restart... so your program might require saving and restoring of program state. /// You can listen for this in general by hooking onto this event "Application.ApplicationExit += ..." /// However, their is no way to differentiate between UAC starting the application shutdown/restart, and a normal shutdown, /// so i included additional events: /// /// EscalationStarting /// EscalationCancelled /// EscalationSuccessful /// /// Note: if EscalationGoal = EscalationGoal.StartAnotherApplication then this program will not exit. /// /// 3. When your program restarts, make sure you preserve your programs StartPosition, else it might look sloppy if it suddenly moves from where it /// appears in the greyed out UAC background... but then again... the taskmanager doesn't care about its StartPosition when you press /// "Show processes from all users" and it restarts lol. For me i just use StartPosition = CenterScreen for the affected forms. /// </example> /// <remarks> /// Reference: /// http://www.codeproject.com/KB/vista-security/UAC_Shield_for_Elevation.aspx, /// http://buildingsecurecode.blogspot.com/2007/06/how-to-display-uac-shield-icon-inside.html /// </remarks> public class StudioShieldButton : Button { #region Fields
public delegate void EscalationHandler(EscalationGoal escalationGoal, object sender, EventArgs e);
#endregion
#region Properties
#region FlatStyle Appearance Property
/// <summary> /// Determines the appearance of the control when a user moves the mouse the mouse over the control and clicks. /// </summary> [ Category("Appearance"), Description("Determines the appearance of the control when a user moves the mouse the mouse over the control and clicks."), DefaultValue(typeof(FlatStyle), "System"), ReadOnly(true), Browsable(false) ] public new FlatStyle FlatStyle { get { return base.FlatStyle; } }
#endregion
#region AlwaysShowShield Appearance Property
private bool alwaysShowShield = false; /// <summary> /// Gets or sets if the shield icon should always be visible. /// </summary> [ Category("Appearance"), Description("Gets or sets if the shield icon should always be visible."), DefaultValue(typeof(bool), "false"), ] public bool AlwaysShowShield { get { return alwaysShowShield; } set { alwaysShowShield = value;
if (!UACUtilities.HasAdminPrivileges() || alwaysShowShield) // then show the shield on the button { // Show the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(1)); // the (1) for true }
else { // Hide the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(0)); // the (0) for false }
} }
#region Serialization /// <summary> /// Should serialize AlwaysShowShield property. /// </summary> /// <returns>True if should serialize, else false.</returns> private bool ShouldSerializeAlwaysShowShield() { //Only serialize nondefault values return (alwaysShowShield != false); } /// <summary> /// Resets AlwaysShowShield property. /// </summary> private void ResetAlwaysShowShield() { alwaysShowShield = false;
if (UACUtilities.HasAdminPrivileges()) // then show the shield on the button { // Show the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(1)); // the (1) for true }
else { // Hide the shield SendMessage(new HandleRef(this, this.Handle), BCM_SETSHIELD, new IntPtr(0), new IntPtr(0)); // the (0) for false } } #endregion
#endregion
#region EscalationGoal Behavior Property
private EscalationGoal escalationGoal = EscalationGoal.StartAnotherApplication; /// <summary> /// Gets or sets the EscalationGoal for this UAC "shield" button. /// </summary> [ Category("Behavior"), Description("Gets or sets the EscalationGoal for this UAC \"shield\" button."), DefaultValue(typeof(EscalationGoal), "StartAnotherApplication") ] public EscalationGoal EscalationGoal { get { return escalationGoal; } set { escalationGoal = value; } }
#region Serialization /// <summary> /// Should serialize EscalationGoal property. /// </summary> /// <returns>True if should serialize, else false.</returns> private bool ShouldSerializeEscalationGoal() { //Only serialize nondefault values return (escalationGoal != EscalationGoal.StartAnotherApplication); } /// <summary> /// Resets EscalationGoal property. /// </summary> private void ResetEscalationGoal() { escalationGoal = EscalationGoal.StartAnotherApplication; } #endregion
#endregion
#region EscalationCustomProcessPath Behavior Property
private string escalationCustomProcessPath = String.Empty; /// <summary> /// Gets or sets the path to the application that this program starts when hit. /// Leave it \"\" to load the current Application.ExecutablePath. /// </summary> [ Category("Behavior"), Description("Gets or sets the path to the application that this program starts when hit. Leave it \"\" to load the current Application.ExecutablePath."), DefaultValue(typeof(string), "\"\""), Editor(typeof(FilteredFileNameEditor /*FileNameEditor*/), typeof(UITypeEditor)) ] public string EscalationCustomProcessPath { get { return escalationCustomProcessPath; } set { escalationCustomProcessPath = value; } }
#region Serialization /// <summary> /// Should serialize EscalationCustomProcessPath property. /// </summary> /// <returns>True if should serialize, else false.</returns> private bool ShouldSerializeEscalationCustomProcessPath() { //Only serialize nondefault values return (escalationCustomProcessPath != String.Empty); } /// <summary> /// Resets EscalationCustomProcessPath property. /// </summary> private void ResetEscalationCustomProcessPath() { escalationCustomProcessPath = String.Empty; } #endregion
#endregion
#endregion
#region DllImports
private const uint BCM_SETSHIELD = 0x0000160C;
[DllImport("user32.dll")] private static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
#endregion
#region Constructor
public StudioShieldButton() { base.FlatStyle = FlatStyle.System; // This must be FlatStyle.System for the shield to work // I also locked the FlatStyle property: // DefaultValue(typeof(FlatStyle), "System"), // ReadOnly(true), // Browsable(false) // so hopefully vs.net won't try to serialize it.
AlwaysShowShield = alwaysShowShield; //i'm forcing the code in the Set{} of "AlwaysShowShield" to run. }
#endregion
#region Members
private string EscalationProcessPath() { string path;
if (escalationGoal == EscalationGoal.StartAnotherApplication) { if (String.IsNullOrEmpty(escalationCustomProcessPath)) throw new Exception("escalationGoal == EscalationGoal.StartAnotherApplication but escalationCustomProcessPath is null or empty.");
path = escalationCustomProcessPath; }
else path = Application.ExecutablePath;
return path; }
private void OnEscalationStarting(EscalationGoal escalationGoal, object sender, EventArgs e) { if (EscalationStarting != null) { EscalationStarting(escalationGoal, sender, e); } }
private void OnEscalationCancelled(EscalationGoal escalationGoal, object sender, EventArgs e) { if (EscalationCancelled != null) { EscalationCancelled(escalationGoal, sender, e); } }
private void OnEscalationSuccessful(EscalationGoal escalationGoal, object sender, EventArgs e) { if (EscalationSuccessful != null) { EscalationSuccessful(escalationGoal, sender, e); } }
#endregion
#region Overrided Members
protected override void OnClick(EventArgs e) { if (UACUtilities.HasAdminPrivileges()) base.OnClick(e); // this can only be called if we're an admin, we are assuming it contains admin-only stuff
else { UACUtilities.AttemptPrivilegeEscalation( EscalationProcessPath(), delegate() { OnEscalationStarting(escalationGoal, this, new EventArgs()); }, delegate() { OnEscalationCancelled(escalationGoal, this, new EventArgs()); }, delegate() { OnEscalationSuccessful(escalationGoal, this, new EventArgs());
if (escalationGoal == EscalationGoal.RestartThisApplication) Application.Exit(); }); } }
#endregion
#region Events
#region EscalationStarting Action
[Category("Action")] [Description("A UAC privilege escalation is going to start next.")] public event EscalationHandler EscalationStarting;
#endregion
#region EscalationCancelled Action
[Category("Action")] [Description("The user cancelled the UAC privilege escalation prompt.")] public event EscalationHandler EscalationCancelled;
#endregion
#region EscalationSuccessful Action
[Category("Action")] [Description("The user was successful in getting admin privileges.")] public event EscalationHandler EscalationSuccessful;
#endregion
#endregion }
public class UACUtilities { #region Fields
public delegate void EscalationEvent();
#endregion
#region Members
public static bool HasAdminPrivileges() { WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); WindowsPrincipal windowsPrincipal = new WindowsPrincipal(windowsIdentity); return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator); }
public static ProcessStartInfo EscalationProcessStartInfo(string path) { if (String.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
if (!File.Exists(path)) throw new FileNotFoundException("path");
ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.UseShellExecute = true; startInfo.FileName = path; startInfo.Verb = "runas"; // will bring up the UAC run-as menu when this ProcessStartInfo is used
return startInfo; }
public static void AttemptPrivilegeEscalation(string path) { if (String.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
AttemptPrivilegeEscalation(path, null, null, null); }
public static void AttemptPrivilegeEscalation(string path, EscalationEvent starting, EscalationEvent cancelled, EscalationEvent successful) { if (String.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
if (!File.Exists(path)) throw new FileNotFoundException("path");
if (HasAdminPrivileges()) throw new SecurityException("Already have administrator privileges.");
ProcessStartInfo startInfo = EscalationProcessStartInfo(path);
if(starting != null) starting();
////todo: slight issue with this... when the program is in admin status... ////if my EscalationCustomProcessPath is set to some random program that goes online right away ////i get norton saying this application program (not the other program) is trying to connect to the internet...
try { Process.Start(startInfo); }
catch (System.ComponentModel.Win32Exception) //occurs when the user has clicked Cancel on the UAC prompt. { if(cancelled != null) cancelled(); return; // By returning, we are ignoring the user tried to get UAC priviliges but then hit cancel at the "Run-As" prompt. }
if(successful != null) successful(); }
#endregion }
public enum EscalationGoal { RestartThisApplication, StartAnotherApplication }
//http://72.14.205.104/search?q=cache:2HrHWneYMSAJ:forums.microsoft.com/MSDN/ShowPost.aspx%3FPostID%3D66703%26SiteID%3D1+UITypeEditor+directory+path+Editor+property&hl=en&ct=clnk&cd=2&gl=us internal class FilteredFileNameEditor : UITypeEditor { private OpenFileDialog ofd = new OpenFileDialog();
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { ofd.FileName = value.ToString(); ofd.Filter = "Programs|*.exe|All Files|*.*"; //ofd.Filter = "Programs|*.exe;*.pif,*.com;*.bat;*.cmd|All Files|*.*"; //ofd.Filter = "Text File|*.txt|All Files|*.*"; if (ofd.ShowDialog() == DialogResult.OK) { return ofd.FileName; } return base.EditValue(context, provider, value); } } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Wow... i am sorry i dont want to offend you but posting comments like yours is way annyoing.
Dont you think it would be better to create an article here for that Control or write a Blog-Entry about your Control and just post the link instead of posting the whole code as a comment?
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
 |
Dont know about other editions of Vista but for Vista Home, if you add a second user and make them a member of the administrator group..then do a builtin\Administrator check ..the IsInRole check will return false.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Nice article, thanks for taking the time to write it.
Firstly I just wanted to get the shield to appear so I added this part to my user control .ctor after the initialize component.
SendMessage(bt.Handle, BCM_SETSHIELD, 0, 0xFFFFFFFF);
and [DllImport("user32")] public static extern UInt32 SendMessage (IntPtr hWnd, UInt32 msg, UInt32 wParam, UInt32 lParam);
internal const int BCM_FIRST = 0x1600; //Normal button internal const int BCM_SETSHIELD = (BCM_FIRST + 0x000C);
however I still see the old battleship grey button.
I compiled using .NET 2, do I need to use v3?
Thanks!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Ah, no apparently it's the old nugget
Application.EnableVisualStyles();
which I was missing. I could have sworn (actually I will swear right now!) that the msdn docs say EnableVisualStyles() isn't needed in .NET 2 (and presumably 3?!). So is this just a Vista thing now.
Use Application.EnableVisualStyles() when using .NET 1 and XP, or any .NET and Vista. No need to use it with .NET 2 and XP.
And what about all the buggyness related to it?
Ugh, rant over, back to work(arounds).
thanks for the article.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
It works with windows 7 too!  The button shows the win7 version of the shield
Well, not a big suprise... because it's using the same API's but... it works 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
static internal bool IsAdmin() { WindowsIdentity id = WindowsIdentity.GetCurrent(); WindowsPrincipal p = new WindowsPrincipal(id); return p.IsInRole(@"BUILTIN\Administrators"); }
...does not work on a danish Vista and probably not on any non-english versions of Vista, because "BUILTIN\Administrators" does not exists on these versions. In danish the admin-group is "BUILTIN\Administratorer".
Your should use the WindowsBuildInRole.Administrator enum instead:
static internal bool IsAdmin() { WindowsIdentity id = WindowsIdentity.GetCurrent(); WindowsPrincipal p = new WindowsPrincipal(id); return p.IsInRole(WindowsBuiltInRole.Administrator); }
This should work on any language. 
Best Regards.
|
| Sign In·View Thread·PermaLink | 4.50/5 (8 votes) |
|
|
|
 |
|
|
 |
|