90

I have an application that needs to detect whether or not it is running with elevated privileges or not. I currently have code set up like this:

static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole (WindowsBuiltInRole.Administrator);
}

This works to detect if a user is an administrator or not, but doesn't work if running as an administrator without elevation. (For example in vshost.exe).

How can I determine whether or not elevation is [already in force or] possible?

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
MiffTheFox
  • 21,302
  • 14
  • 69
  • 94

10 Answers10

59

Try this out:

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;

public static class UacHelper
{
    private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
    private const string uacRegistryValue = "EnableLUA";

    private static uint STANDARD_RIGHTS_READ = 0x00020000;
    private static uint TOKEN_QUERY = 0x0008;
    private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength);

    public enum TOKEN_INFORMATION_CLASS
    {
        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
    }

    public enum TOKEN_ELEVATION_TYPE
    {
        TokenElevationTypeDefault = 1,
        TokenElevationTypeFull,
        TokenElevationTypeLimited
    }

    public static bool IsUacEnabled
    {
        get
        {
            RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false);
            bool result = uacKey.GetValue(uacRegistryValue).Equals(1);
            return result;
        }
    }

    public static bool IsProcessElevated
    {
        get
        {
            if (IsUacEnabled)
            {
                IntPtr tokenHandle;
                if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle))
                {
                    throw new ApplicationException("Could not get process token.  Win32 Error Code: " + Marshal.GetLastWin32Error());
                }

                TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;

                int elevationResultSize = Marshal.SizeOf((int)elevationResult);
                uint returnedSize = 0;
                IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize);

                bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint)elevationResultSize, out returnedSize);
                if (success)
                {
                    elevationResult = (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(elevationTypePtr);
                    bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull;
                    return isProcessAdmin;
                }
                else
                {
                    throw new ApplicationException("Unable to determine the current elevation.");
                }
            }
            else
            {
                WindowsIdentity identity = WindowsIdentity.GetCurrent();
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                bool result = principal.IsInRole(WindowsBuiltInRole.Administrator);
                return result;
            }
        }
    }
}
Fábio Junqueira
  • 2,701
  • 21
  • 20
Steven
  • 4,826
  • 3
  • 35
  • 44
  • 8
    Works if the account to run as is a local administrator but if you use the domain administrator the variable isProcessAdmin returns false. But UAC accepts the Domain Administrator as valid when elevating privileges (create folder in windows, run as administrator, etc)...How can i modify your function so it takes into account that case too? – VSP Dec 18 '12 at 13:01
  • 1
    You might also want to consider that if the account is the built in administrator then UAC is elevated by default so IsProcessElevated will return false in this case (because IsUacEnabled is true and elevationResult is TokenElevationTypeDefault) even though the process runs with in elevated mode without having prompted the user. Or in other words the account is elevated and the process runs in the default elevation type. – Mister Cook Nov 16 '13 at 11:17
  • 2
    This code requires the following using statements: using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Principal; It also seems to be mirrored [here.](http://www.sadrobot.co.nz/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/) – Scott Solmer Apr 28 '14 at 17:17
  • This got me an exception at Windows 8, at `Marshal.SizeOf((int)elevationResult)` I am not sure why yet. Exception message is: Method not found. At: `Int32 System.Runtime.InteropServices.Marshal.SizeOf(!!0).` – CularBytes Jun 07 '16 at 16:19
  • What about TokenElevationTypeLimited ? Should it not be considered to set isProcessAdmin to true ? –  Dec 16 '16 at 10:19
  • This code works pretty well with Visual Studio Setup project custom actions.I am trying to move to InstallShield installer basic msi project and calling the same above code gives me different values. elevationResult value is different with VS vs. IS installers when running on same machine with same user. VS Installer: elevationResult value is TokenElevationTypeDefault and IsAdministrator is true. IS Installer: elevationResult value is TokenElevationTypeFull and IsAdministrator is false. Anyone observed same issue? Any ideas why different behavior? – Santhosh Oct 12 '18 at 16:03
39

(new answer six years after the question was asked)

Disclaimer: This is just something that happened to work on my particular OS with my particular settings with my particular user:

using System.Security.Principal;

// ...

    static bool IsElevated
    {
      get
      {
        return WindowsIdentity.GetCurrent().Owner
          .IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
      }
    }

So when I run this "Run as administrator", the property get accessor returns true. When running normally (even if my user "is" administrator, just not running this particular application "as administrator"), it returns false.

This seems much simpler than many other answers.

I have no idea if there are cases where this fails.

PS! This also seems OK:

    static bool IsElevated
    {
      get
      {
        var id = WindowsIdentity.GetCurrent();
        return id.Owner != id.User;
      }
    }
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • 1
    Thanks for this! - I used this in PowerShell [Security.Principal.WindowsIdentity]::GetCurrent().Owner.IsWellKnown([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid) – Lewis Nov 02 '15 at 16:44
  • When having set notifications to 'never show any notification', this will return true. Perhaps in certain scenario's where you really need to run the software as administrator it can give a false indication. – CularBytes Mar 08 '16 at 21:25
  • 4
    This will not distinguish between "semi-unelevated" process and a properly-unelevated process: it's possible that `IsElevated` will return false but the process may still be running with High integrity level. A genuinely non-elevated process has a medium integrity level. This is probably irrelevant for 99% of the applications, but it's worth mentioning because tools like Process Hacker might still declare such a process to be elevated. A "semi-unelevated" process is not something you'd see normally; it might occur when someone fails to launch an unelevated child process correctly. – Roman Starkov Nov 18 '16 at 23:19
  • Whats "running with High integrity level"? – StingyJack Oct 01 '17 at 17:49
  • 1
    @StingyJack that's too big of a question to answer in comments, but see [here](https://msdn.microsoft.com/en-us/library/bb625957.aspx) and [here](https://msdn.microsoft.com/en-us/library/bb625963.aspx). – Roman Starkov Oct 01 '17 at 21:48
  • Thanks @RomanStarkov and Jeppe, 20+ years in the business and I hadn't heard the term before. – StingyJack Oct 02 '17 at 00:41
  • How to check for other process (by name) , i.e. if `other_process.exe` running in admin or not? – T.Todua Mar 13 '20 at 17:20
  • 1
    This isn't really right, the owner of a security token generally will be admin if it's an elevated token but it doesn't actually have to be. Also you can have a non-elevated security token owned by admin. The true test of whether a token is elevated is whether it has the admin SID in list of granted access SIDs in the ACLs because that's what will actually make it pass the ACL test. – Benj Mar 16 '21 at 10:39
22

Here is a modified version of this answer to include things like the proper disposing of resources and handling of Domain Administrators.

public static class UacHelper
{
    private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
    private const string uacRegistryValue = "EnableLUA";

    private static uint STANDARD_RIGHTS_READ = 0x00020000;
    private static uint TOKEN_QUERY = 0x0008;
    private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength);

    public enum TOKEN_INFORMATION_CLASS
    {
        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
    }

    public enum TOKEN_ELEVATION_TYPE
    {
        TokenElevationTypeDefault = 1,
        TokenElevationTypeFull,
        TokenElevationTypeLimited
    }

    public static bool IsUacEnabled
    {
        get
        {
            using (RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false))
            {
                bool result = uacKey.GetValue(uacRegistryValue).Equals(1);
                return result;
            }
        }
    }

    public static bool IsProcessElevated
    {
        get
        {
            if (IsUacEnabled)
            {
                IntPtr tokenHandle = IntPtr.Zero;
                if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle))
                {
                    throw new ApplicationException("Could not get process token.  Win32 Error Code: " +
                                                   Marshal.GetLastWin32Error());
                }

                try
                {
                    TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;

                    int elevationResultSize = Marshal.SizeOf(typeof(TOKEN_ELEVATION_TYPE));
                    uint returnedSize = 0;

                    IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize);
                    try
                    {
                        bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType,
                                                           elevationTypePtr, (uint) elevationResultSize,
                                                           out returnedSize);
                        if (success)
                        {
                            elevationResult = (TOKEN_ELEVATION_TYPE) Marshal.ReadInt32(elevationTypePtr);
                            bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull;
                            return isProcessAdmin;
                        }
                        else
                        {
                            throw new ApplicationException("Unable to determine the current elevation.");
                        }
                    }
                    finally
                    {
                        if (elevationTypePtr != IntPtr.Zero)
                            Marshal.FreeHGlobal(elevationTypePtr);
                    }
                }
                finally
                {
                    if (tokenHandle != IntPtr.Zero)
                        CloseHandle(tokenHandle);
                }
            }
            else
            {
                WindowsIdentity identity = WindowsIdentity.GetCurrent();
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                bool result = principal.IsInRole(WindowsBuiltInRole.Administrator) 
                           || principal.IsInRole(0x200); //Domain Administrator
                return result;
            }
        }
    }
}
Community
  • 1
  • 1
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • It all depends on which user you are running the service as. Are you trying to detect if the service is running as Local System, Local Service, Network Service, or a windows user? Detecting "administrative status" wont work for telling the difference between Local System and Local Service, you need to test for that by checking directly which user is running the process. – Scott Chamberlain Aug 08 '13 at 02:31
  • This got me an exception at Windows 8, at `Marshal.SizeOf((int)elevationResult)` I am not sure why yet. Exception message is: Method not found. At: `Int32 System.Runtime.InteropServices.Marshal.SizeOf(!!0).` – CularBytes Jun 07 '16 at 16:19
  • @RageCompex are you using a restricted platform like a universal app or Unity3d? – Scott Chamberlain Jun 07 '16 at 16:21
  • Well it is a customer that I receive the error from, automatic logging, All I know is that it doesn't work on his/her pc. All I know until now is that it is a Windows 8, 64x bit, 2 processors. I suspect it is due old .NET version, `Marshal.SizeOf` is supported since 4.5.1 I can read elsewhere.. – CularBytes Jun 07 '16 at 16:32
  • @RageCompex its been available [sense .NET 1.1](https://msdn.microsoft.com/en-us/library/y3ybkfb3(v=vs.110).aspx#Anchor_4). Perhaps you have a typo? – Scott Chamberlain Jun 07 '16 at 16:35
  • Yea, thats what I thought :( No it is working correctly on mine and about 100 others... full stack trace: http://pastebin.com/ebSWARfu – CularBytes Jun 07 '16 at 16:40
  • 1
    Ah, you are compiling with 4.5.1 because of that it is trying to use [this overload](https://msdn.microsoft.com/en-us/library/dn261467(v=vs.110).aspx) but the user does not have 4.5.1 installed. Try replacing it with `Marshal.SizeOf(typeof(TOKEN_ELEVATION_TYPE))`, – Scott Chamberlain Jun 07 '16 at 16:46
  • Thanks @ScottChamberlain The user updated to 4.5.2 (which I target) and it solved the problem. This solution is probably good for backwards compatibility. – CularBytes Jun 07 '16 at 20:40
  • 2
    @ScottChamberlain `int elevationResultSize = Marshal.SizeOf(typeof(TOKEN_ELEVATION_TYPE))` throws an `ArgumentException` on 32 Bit application .NET 4.0, `int elevationResultSize = Marshal.SizeOf((int)elevationResult)` worked, however. – Martin Braun Jul 28 '16 at 14:12
  • This answer does not detect elevation on Windows Server 2019 on an administrator account. However, this answer does: https://stackoverflow.com/a/55079599/6079533 – A. Niese Nov 11 '21 at 23:28
16

NB: This is an old answer which was more relevant when the question was originally written and was how you could do this in managed c++ (the .net version of c++), as it was much harder to solve this in C# back then. You build this in a separate assembly and reference it in your c# project as normal

The CodePlex project UAChelper has code that checks on elevation in UserAccountControl.cpp UserAccountControl::IsUserAdmin, which checks if UAC is enabled and then checks if the process is elevated.

bool UserAccountControl::IsCurrentProcessElevated::get()
{
    return GetProcessTokenElevationType() == TokenElevationTypeFull;    //elevated
}

from the function:

int UserAccountControl::GetProcessTokenElevationType()
{
    HANDLE hToken;
    try
    {
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
            throw gcnew Win32Exception(GetLastError());

        TOKEN_ELEVATION_TYPE elevationType;
        DWORD dwSize;
        if (!GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize))
            throw gcnew Win32Exception(GetLastError());

        return elevationType;
    }
    finally
    {
        CloseHandle(hToken);
    }
}
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
  • This appears to be c++ code, not the requested c# code. – John Lord Mar 09 '23 at 02:50
  • @JohnLord This is managed C++ (.net) and not plain c++. I believe that when I wrote obtained answer 14 years ago, doing it in C# was not as easy/possible as it is now. I can't be sure anymore as I don't have the tooling of the period any more. But your point is fair. – Preet Sangha Mar 09 '23 at 17:53
  • well i didn't downvote or anything. However, if your solution is managed c, you should explain how to include that in the c# project. I've been programming in c# 5 years, and i don't know how to do that. I think you have to include it as a separate project but not sure. – John Lord Mar 09 '23 at 20:50
11

In .net Framwork 4.5 I found another method that works for me. In relation to the following script that can be found here here (in German)

 rem --- Admintest.bat ---
 whoami /groups | find "S-1-5-32-544" > nul
 if errorlevel 1 goto ende
 echo Benutzer %username% ist lokaler Administrator.
 :ende

In C# it looks like this:

    private bool IsAdmin
    {
        get
        {
            WindowsIdentity identity = WindowsIdentity.GetCurrent();
            if (identity != null)
            {
               WindowsPrincipal principal = new WindowsPrincipal(identity);
               List<Claim> list = new List<Claim>(principal.UserClaims);
               Claim c = list.Find(p => p.Value.Contains("S-1-5-32-544"));
               if (c != null)
                  return true;
            }
            return false;
        }
    }

But in .net < 4.5 the WindowsPrincipal class does not contain the UserClaims property and I found no way to get this information.

Rafael
  • 555
  • 1
  • 7
  • 15
  • 2
    FYI: Only determining if account is administrator, not if the app is elevated – CularBytes Jun 07 '16 at 16:33
  • To do check if a user is a member of S-1-5-32-544 (Administrators group) in .Net < 4.5, you can just use the code in the original question. The principal will only be a member of the Administrators group if the process is running elevated and the user is in the group. If the process is not elevated the principal will not be in the group. – Adam Jan 18 '18 at 01:17
  • 1
    Nice answer, short and efficient, I gave you a +1 for it. N.B. I made this a property in my code (`private bool IsAdmin{ get { ... } }`), then you don't need the brackets if you invoke `IsAdmin`. – Matt Apr 03 '18 at 14:20
5

Using TokenElevationType would work, but if you PInvoke CheckTokenMembership() against the admin group SID, your code would also work when UAC is off and on 2000/XP/2003 and will also handle deny SID's.

There is also a IsUserAnAdmin() function that does the CheckTokenMembership check for you, but MSDN says it might not be there forever

joe
  • 8,344
  • 9
  • 54
  • 80
Anders
  • 97,548
  • 12
  • 110
  • 164
  • I found CheckTokenMembership insufficient when subject to UAC - https://github.com/chocolatey/choco/blob/25cd37f3259383e2bcd8903b1272c17befac2232/src/chocolatey/infrastructure/information/ProcessInformation.cs#L51 returns false. Check the code (I'm replacing it) and take a look at the output from Win2012R2 - http://i.imgur.com/gX3JP0W.png – ferventcoder Feb 09 '15 at 14:54
  • @ferventcoder It depends on what you really want to know; is the user a elevated administrator right now or can they elevate if required. You can for example check TOKEN_ELEVATION_TYPE and end up with something like: bool is_or_can_elevate() { return process_is_elevated() || TokenElevationTypeLimited == get_current_token_elevation_type(); }. Another issue is that the definition of elevated is not the same everywhere, you can have a console window with the "Administrator: " prefix and at the same time be below High integrity level! TokenElevation does not always match TokenIntegrityLevel. – Anders Feb 09 '15 at 20:36
  • Fun times. I want to know if I have an elevated process separate from whether the user is an administrator. Here's where I ended up. Let me know where I should go if it is wrong - https://github.com/chocolatey/choco/issues/77#issuecomment-73523774 and https://github.com/chocolatey/choco/commit/ba2350662154de12e23221551b6338c6d2ae9760 – ferventcoder Feb 09 '15 at 22:59
  • @ferventcoder is_processes_elevated() { return CheckTokenMembership/IsInRole || TokenElevation/TokenIntegrityLevel>=0x3000; } CheckTokenMembership _or_ IsInRole for < Vista and Vista+ with UAC off. TokenElevation _or_ TokenIntegrityLevel>=0x3000 depending on exactly how you want to detect the elevation. I believe conhost.exe uses TokenElevation but it is broken IMHO and you should check the actual level... (You need special tools to generate a token that fools TokenElevation though) See also: https://windowssucks.wordpress.com/2011/02/07/uac-are-you-high/# – Anders Feb 09 '15 at 23:17
  • ...and even that is sort of wrong, in theory it is possible to have a elevated token and not be in the administrators group. So if you only want people in the administrators group and make sure that they are elevated you should perform the CheckTokenMembership/IsInRole check and then the Token* check should fail (No UAC) _or_ it's value should indicate elevation... This of course depends on what the you actually want to access. You might need to be system/admin and elevated, or just elevated, it depends on the ACL. – Anders Feb 09 '15 at 23:21
  • Yep, if you read my comments in there you can see I mention that. We only use the detection for informational purposes now. – ferventcoder Feb 10 '15 at 13:06
  • Reading over that code, we check a user first based on a quick win (IsInRole), then switch over to the token elevation. In most cases we are going to catch administrators who are not elevated but in some minor cases we may catch others as well. We'll generate a warning when is_admin and is_process_elevated don't match. – ferventcoder Feb 10 '15 at 13:09
5

This Answer has a few problems. First, it doesn't get any System processes that run as Admin (for example under NT-Authority/SYSTEM). The code example below fixes all problems (detects, LocalAdmins, DomainAdmins, and LocalSystemAdmins)

If you just want the current Process, replace pHandle with Process.GetCurrentProcess().Handle

NOTE: You must have certain privileges to run it. (Every AdminProcess has them but needs to active them first, Services have them activated by default)

internal static bool IsProcessElevatedEx(this IntPtr pHandle) {

        var token = IntPtr.Zero;
        if (!OpenProcessToken(pHandle, MAXIMUM_ALLOWED, ref token))
                throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed");

        WindowsIdentity identity = new WindowsIdentity(token);
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        bool result = principal.IsInRole(WindowsBuiltInRole.Administrator)
                   || principal.IsInRole(0x200); //Domain Administrator
        CloseHandle(token);
        return result;
}
John Smith
  • 573
  • 6
  • 22
3

I think there is one more issue. I checked solutions provided by you and have to say that in the installation of Windows 7 and logged on as an admin the check does not work. Windows never returns information that process runs in an elevated mode. So the sequence:

if (IsUacEnabled)
    return IsProcessInElevatedMode();
return IsUserAdmin();

does not returns true when logged as an Administrator but the process has all privileges to perform system operations (e.g. stop system services). The working sequence is:

if (IsUserAdmin())
    return true;

if (IsUacEnabled)
    return IsProcessInElevatedMode();

return false;

You should first check if the process is run in Administrator context. Additional info:

IsUacEnabled() - checks if the UAC has been enabled in the system (Windows)
IsProcessInElevatedMode() - checks if the process is run in an elevated mode
IsUserAdmin() - checks if the current user has an Administrtor role

All of that methods has been described in previous posts.

1

Using UACHelper nuget package: https://www.nuget.org/packages/UACHelper/

if (UACHelper.IsElevated)
    // something
else
    // something else

There are a lot of other properties that can be used to detect if the user is, in fact, an administrator, or if the process is running under UAC virtualization, or if the desktop owner is the process owner. (Run as from limited account)

Check the read me for more information.

Soroush Falahati
  • 2,196
  • 1
  • 27
  • 38
0

I am using this code and it works well:


bool runningAsAdmin = WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);

*Admin is part of the Build-In Administrators group.

"A user account for the system administrator. This account is the first account created during operating system installation. The account cannot be deleted or locked out. It is a member of the Administrators group and cannot be removed from that group." -- https://ss64.com/nt/syntax-security_groups.html

Blee
  • 24
  • 4
  • Technically this relies on an implementation detail. The fact, that the "owner" field of the token points to the built-in `Administrators` group. However, no one's to say this implementation detail is there to stay and the appropriate method is to check whether [the current security context is elevated or not](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-token_elevation)! – 0xC0000022L Feb 18 '21 at 14:51