BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Security
.NET 1.1

Creating an Elevated Button Control

When using Microsoft Windows Vista, administrative tasks are restricted by the user account control (UAC) system. Buttons that require elevated permissions are displayed with the command text and a shield icon to indicate that permission will be required.

Vista Shield Icon

Microsoft Vista introduced the concept of User Account Control (UAC) to the Windows operating system. The UAC system reduces the risk of viruses and other malware damaging the operating system files and configuration by preventing access to administrative functions. If an attempt is made to access such a function, the user sees a dialog box explaining what has happened and requesting permission from the user before continuing with the process.

The UAC system stops illegal attempts to make system changes. It also shows the dialog box when a valid request is made. Within the standard Vista software, the user knows that this is about to happen because the button or link that they click includes a special shield icon, known as the elevated icon, as pictured below:

Button with UAC shield icon

When you develop your own Windows forms applications that include processes requiring elevated permissions, you should follow the same standard for buttons. Where a button will initiate a protected function, you should show the elevated icon. However, if the user is already running your software with administrative permissions, the shield should not be displayed.

In this article we will construct a new button control for administrative use. The button will automatically display the shield icon when the user is not executing the software as an administrator.

Creating the ElevatedButton Control

The ElevatedButton control will utilise the existing functionality of the standard Button control. We will add some minor modifications to display the shield icon as required. To create the control we will use a simple class library project. Create a new class library project named "ElevatedButtonControl". Rename the default class file to "ElevatedButton.cs". To provide access to the existing Button class, add a reference to System.Windows.Forms to the project.

Subclassing the Button Class

The ElevatedButton class will subclass the standard Button class from the System.Windows.Forms namespace. This will provide all of the standard behaviour of a button without any addition code being required. So that you do not need to fully qualify the reference to the Button class, add the following using directive to the code at the top of the ElevatedButton class file.

using System.Windows.Forms;

With the using directive in place, the class's declaration may be updated to indicate that it inherits from Button, as follows:

public class ElevatedButton : Button
{
}

Referencing SendMessage

It would be possible to add a shield image to a button using the properties of the Button class. However, the elevated icon should not appear when using Windows XP or earlier operating system versions. In future operating systems, it may be that the icon design will be changed or no longer required. To use the Image property, it would be necessary to check for all of these possibilities and modify the image accordingly.

The Windows API provides a function named "SendMessage". This function can be used to send specific messages to windows, where a window is a form or any control within a form. One such message is "BCM_SETSHIELD". When sent to a button, this message requests that the shield icon is displayed on the surface of that button, if supported by the operating system.

In order to use SendMessage, you must use Platform Invocation Services (P/Invoke). To simplify access to the native Windows code, add the following using directive:

using System.Runtime.InteropServices;

You can now add two necessary declarations to the class file. The first will enable calls to the SendMessage function. The second will define an unsigned integer that represents the BCM_SETSHIELD message. Add the following to the class's code block.

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(
    HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

private uint BCM_SETSHIELD = 0x0000160C;

Checking if the Elevated Icon is Required

The elevated icon only needs to be displayed if the user does not currently have elevated privileges. We will add a new method, named "IsElevated", to the class to check if the program is running as an administrator. This method will return true if the shield icon is not required and false otherwise.

The method requires another using directive:

using System.Security.Principal;

You can now add the method to the ElevatedButton class:

private bool IsElevated()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
6 April 2009