How to check if the current user is an Administrator (even if UAC is on)
There may be a scenario where you want to determine from code if the current user is an Administrator.
One example of this which I have had to deal with is checking for software updates.
Say your application contacts a service to see if there is a newer version of the application available; if so, you can download and run the installer.
Imagine that the installer requires admin privileges; you don’t want to run the installer if the current user does not have administrative privileges.
So how can we check if the user is an admin or not?
In VB6, C++ etc
There is a Windows API function you can use very easily to see if the current user is an admin: IsUserAnAdmin.
BOOL IsUserAnAdmin(void);
Visual Basic 6 Declaration
    Private Declare Function IsUserAnAdmin Lib “Shell32″ Alias "#680″ () As Integer
While you can still use this, it is actually deprecated, and the documentation recommends you call the CheckTokenMembership function instead (which IsUserAnAdmin is a wrapper for).
C# .NET
using System;
using System.Security.Principal;
var identity = WindowsIdentity.GetCurrent();
if (identity == null) throw new InvalidOperationException("Couldn't get the current user identity");
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
User Account Control (UAC)
A problem arises when you use any of the above code on a machine that has UAC enabled, and the process is not elevated.
While the user may be an administrator, when the process is not elevated yet, the user has a split token – which doesn’t have the administrator privileges.
A way around this is to use the GetTokenInformation API call to inspect the token to see if it’s a split token. In most cases this will mean that UAC is on and the current user is an administrator.
This is not 100% reliable (see References) but it’s probably the best we can do for now.
C#
This code is slightly easier in .NET, as there’s already a fair amount of code we don’t have to write to get the current process’s token.
First, we’ll need some code to support the GetTokenInformation API call:
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetTokenInformation(IntPtr tokenHandle, TokenInformationClass tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
/// <summary>
/// Passed to <see cref="GetTokenInformation"/> to specify what
/// information about the token to return.
/// </summary>
enum TokenInformationClass
{
     TokenUser = 1,
     TokenGroups,
     TokenPrivileges,
     TokenOwner,
     TokenPrimaryGroup,
     TokenDefaultDacl,
     TokenSource,
     TokenType,
     TokenImpersonationLevel,
     TokenStatistics,
     TokenRestrictedSids,
     TokenSessionId,
     TokenGroupsAndPrivileges,
     TokenSessionReference,
     TokenSandBoxInert,
     TokenAuditPolicy,
     TokenOrigin,
     TokenElevationType,
     TokenLinkedToken,
     TokenElevation,
     TokenHasRestrictions,
     TokenAccessInformation,
     TokenVirtualizationAllowed,
     TokenVirtualizationEnabled,
     TokenIntegrityLevel,
     TokenUiAccess,
     TokenMandatoryPolicy,
     TokenLogonSid,
     MaxTokenInfoClass
}
/// <summary>
/// The elevation type for a user token.
/// </summary>
enum TokenElevationType
{
    TokenElevationTypeDefault = 1,
    TokenElevationTypeFull,
    TokenElevationTypeLimited
}
Then, the actual code to detect if the user is an Administrator (returning true if they are, otherwise false).
var identity = WindowsIdentity.GetCurrent();
if (identity == null) throw new InvalidOperationException("Couldn't get the current user identity");
var principal = new WindowsPrincipal(identity);
// Check if this user has the Administrator role. If they do, return immediately.
// If UAC is on, and the process is not elevated, then this will actually return false.
if (principal.IsInRole(WindowsBuiltInRole.Administrator)) return true;
// If we're not running in Vista onwards, we don't have to worry about checking for UAC.
if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major < 6)
{
     // Operating system does not support UAC; skipping elevation check.
     return false;
}
int tokenInfLength = Marshal.SizeOf(typeof(int));
IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength);
try
{
    var token = identity.Token;
    var result = GetTokenInformation(token, TokenInformationClass.TokenElevationType, tokenInformation, tokenInfLength, out tokenInfLength);
    if (!result)
    {
        var exception = Marshal.GetExceptionForHR( Marshal.GetHRForLastWin32Error() );
        throw new InvalidOperationException("Couldn't get token information", exception);
    }
    var elevationType = (TokenElevationType)Marshal.ReadInt32(tokenInformation);
    switch (elevationType)
    {
        case TokenElevationType.TokenElevationTypeDefault:
            // TokenElevationTypeDefault - User is not using a split token, so they cannot elevate.
            return false;
        case TokenElevationType.TokenElevationTypeFull:
            // TokenElevationTypeFull - User has a split token, and the process is running elevated. Assuming they're an administrator.
            return true;
        case TokenElevationType.TokenElevationTypeLimited:
            // TokenElevationTypeLimited - User has a split token, but the process is not running elevated. Assuming they're an administrator.
            return true;
        default:
            // Unknown token elevation type.
            return false;
     }
}
finally
{    
    if (tokenInformation != IntPtr.Zero) Marshal.FreeHGlobal(tokenInformation);
}
Visual Basic 6 (VB6)
For Visual Basic 6, there’s some additional code, as we need to get the token for the current process, and use more calls to also get the operating system version.
Type OSVERSIONINFO
  dwOSVersionInfoSize As Long
  dwMajorVersion As Long
  dwMinorVersion As Long
  dwBuildNumber As Long
  dwPlatformId As Long
  szCSDVersion As String * 128
End Type
' dwPlatformId values
Public Const VER_PLATFORM_WIN32s =
Public Const VER_PLATFORM_WIN32_WINDOWS = 1
Public Const VER_PLATFORM_WIN32_NT = 2
Public Declare Function GetVersionEx Lib "kernel32″ Alias "GetVersionExA" (ByRef lpVersionInformation As OSVERSIONINFO) As Long
' These functions are for getting the process token information, which IsUserAnAdministrator uses to
' handle detecting an administrator that's running in a non-elevated process under UAC.
Private Const TOKEN_READ As Long = &H20008
Private Const TOKEN_ELEVATION_TYPE As Long = 18
Private Declare Function IsUserAnAdmin Lib "Shell32″ Alias "#680″ () As Integer
Private Declare Function CloseHandle Lib "kernel32″ (ByVal hObject As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal TokenInformationClass As Long, TokenInformation As Any,_ ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Public Function IsUserAnAdministrator() As Boolean
    On Error GoTo IsUserAnAdministratorError
    IsUserAnAdministrator = False
    If IsUserAnAdmin() Then
        IsUserAnAdministrator = True
        Exit Function
    End If
    
    ' If we're on Vista onwards, check for UAC elevation token
    ' as we may be an admin but we're not elevated yet, so the
    ' IsUserAnAdmin() function will return false
    Dim osVersion As OSVERSIONINFO
    osVersion.dwOSVersionInfoSize = Len(osVersion)
    
    If GetVersionEx(osVersion) = Then
        Exit Function
    End If
    
    If osVersion.dwPlatformId <> VER_PLATFORM_WIN32_NT Or osVersion.dwMajorVersion < 6 Then
        ' If the user is not on Vista or greater, then there's no UAC, so don't bother checking.
        Exit Function
    End If
    Dim result As Long
    Dim hProcessID As Long
    Dim hToken As Long
    Dim lReturnLength As Long
    Dim tokenElevationType As Long
    
    ' We need to get the token for the current process
    hProcessID = GetCurrentProcess()
    
    If hProcessID <> Then
        If OpenProcessToken(hProcessID, TOKEN_READ, hToken) = 1 Then
            result = GetTokenInformation(hToken, TOKEN_ELEVATION_TYPE, tokenElevationType, 4, lReturnLength)
            If result = Then
                ' Couldn't get token information
                Exit Function
            End If
    
            If tokenElevationType <> 1 Then
                IsUserAnAdministrator = True
            End If
    
            CloseHandle hToken
        End If
    
        CloseHandle hProcessID
    End If
    
    Exit Function
IsUserAnAdministratorError:
' Handle errors
End Function