Check if the current user is an administrator

 
 
  • Gérald Barré

Some actions require a process to run with administrator rights – for example, writing a registry key in HKLM, changing system settings, or writing a file to Program Files. Avoid this when possible, but sometimes it is necessary.

#Check if the current process run as administrator

There are multiple ways to check whether a process runs as administrator:

C#
public bool IsCurrentProcessAdmin()
{
    using var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
    var principal = new System.Security.Principal.WindowsPrincipal(identity);
    return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
}
C#
[DllImport("shell32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsUserAnAdmin();

static bool IsCurrentProcessAdmin()
{
    return IsUserAnAdmin();
}

These methods check whether the current process is running as Administrator. They do not check whether the current user is a member of the Administrators group. Due to User Account Control (UAC), an administrator can run a process without elevated privileges.

The next section explains how UAC works, followed by how to check whether the current user is a member of the Administrators group.

#User Account Control (UAC) & Access token

When you log on, Windows generates an access token containing your security information: identity, groups, privileges, and so on. When you start a process, this token is associated with it. When the process accesses a resource, Windows uses the token to determine whether access is allowed.

When UAC is enabled, Windows generates two access tokens at logon: an administrator token and a standard user token. The standard user token strips all elevated groups and privileges. By default, Windows uses the standard user token when creating processes, which prevents applications from making harmful changes without your consent. To use the administrator token, right-click the application and select "Run as Administrator".

Source: How User Account Control works

You can inspect a process's access token using Process Explorer. In the screenshot below, the admin token is on the left and the filtered token is on the right, showing the difference for the BUILTINS\Administrators group.

the administrator token on the left, the filtered token on the right

In the standard user access token, the BUILTIN\Administrators group has the Deny flag. This means the group is only evaluated against "Deny" rules in ACLs and cannot satisfy "Allow" rules. As a result, a process using the standard user token is not considered to have administrator rights.

#Check if the current user is an administrator

Windows provides an API to query access token information (GetTokenInformation). I have written a .NET library that wraps this API: Meziantou.Framework.Win32.AccessToken (NuGet package, GitHub)

First, add the NuGet package to your project:

csproj (MSBuild project file)
<PackageReference Include="Meziantou.Framework.Win32.AccessToken" Version="1.1.5" />

Then, query the access token to check whether it is a filtered token:

C#
using var token = AccessToken.OpenCurrentProcessToken(TokenAccessLevels.Query);
var isRestricted = token.GetElevationType() == TokenElevationType.Limited;

You can also retrieve the administrator access token (linked token) and check whether it contains the BUILTINS\Administrators group:

C#
public static bool IsUserAdministrator()
{
    using var token = AccessToken.OpenCurrentProcessToken(TokenAccessLevels.Query);
    if (!IsAdministrator(token) && token.GetElevationType() == TokenElevationType.Limited)
    {
        using var linkedToken = token.GetLinkedToken();
        return IsAdministrator(linkedToken);
    }

    return false;

    static bool IsAdministrator(AccessToken accessToken)
    {
        var adminSid = SecurityIdentifier.FromWellKnown(WellKnownSidType.WinBuiltinAdministratorsSid);
        foreach (var group in accessToken.EnumerateGroups())
        {
            if (group.Attributes.HasFlag(GroupSidAttributes.SE_GROUP_ENABLED) && group.Sid == adminSid)
                return true;
        }

        return false;
    }
}

#Restart the process as Administrator

If the current process is using the standard user token and you need administrator rights, you must start a new process. Set the Verb property of ProcessStartInfo to runas to request elevation:

C#
var args = Environment.GetCommandLineArgs();
var psi = new ProcessStartInfo
{
    FileName = args[0],
    UseShellExecute = true,
    Verb = "runas",         // Indicate to run the process as admin
};

// Copy the arguments of the command line
foreach (var arg in args.Skip(1))
{
    psi.ArgumentList.Add(arg);
}

Process.Start(psi);  // Start the new process
Environment.Exit(0); // Terminate the current process

This causes Windows to behave as if the process was launched from Explorer with the "Run as Administrator" command, displaying a UAC consent prompt.

#Use an application manifest to require administrator rights

If your application always requires administrator rights, you can embed an application manifest.

Add a new file of type "Application Manifest File" to create app.manifest, then set <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />:

XML
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">

        <!-- 👇 Add this line -->
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

Windows displays a UAC prompt each time the user starts the program.

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?