11

In my C# application, I need to check if the current user is a member of the Administrators group. It needs to be compatible with both Windows XP and Windows 7.

Currently, I am using the following code:

bool IsAdministrator
{
    get
    {
        WindowsIdentity identity = WindowsIdentity.GetCurrent();
        WindowsPrincipal principal = new WindowsPrincipal(identity);

        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
}

The problem is that this method returns false if the application is run on Windows 7 with UAC turned on as a non-elevated Administrator. How can I determine if the user is an Administrator even if the application is run as a non-elevated Administrator?

markyd13
  • 709
  • 6
  • 15
  • 3
    Why do you want to know that? – svick Apr 06 '12 at 14:55
  • 4
    Well, for one, knowing if you are an administrator allows you to know if you *can* be elevated. – leviathanbadger Apr 06 '12 at 14:57
  • @svick: I need to display certain UI elements if the user is a member of the Administrators group. – markyd13 Apr 06 '12 at 15:00
  • Take a look at [http://www.davidmoore.info/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/](http://www.davidmoore.info/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/) – Raj Ranjhan Apr 06 '12 at 15:02
  • @aboveyou00, can't you elevate yourself as another user, if you know the password? – svick Apr 06 '12 at 15:05
  • 1
    I agree with @svick - you shouldn't need to do this. You want permissions? Try to elevate. Don't make assumptions that a user will always run as an unelevated administrator. It's an acceptable usage to run as a standard user, and elevate using a different admin account. Flow with it, and let the UAC mechanism do its job regardless of how the user works. – Avner Shahar-Kashtan Apr 06 '12 at 15:14
  • @svick: That's true. But if you are an administrator, you don't need to know anybody else's credentials in order to elevate, so IMO it's still useful to know. – leviathanbadger Apr 06 '12 at 15:21
  • @AvnerShahar-Kashtan: I'm not making the assumption that a user is always running as a non-elevated Administrator. I simply need to determine if the user is a member of the Administrators group, both elevated and non-elevated. This also includes the case where a standard user is elevated using a different Administrator account. – markyd13 Apr 06 '12 at 15:27

4 Answers4

18

There is a Win32 API GetTokenInformation that can be used to check the current token. If the returned token is a split token, it probably is an administrator user that is running i non elevated mode.

GetTokenInformation has an output parameter tokenInformation which takes one of three values:

  • TokenElevationTypeDefault = 1
  • TokenElevationTypeFull = 2
  • TokenElevationTypeLimited = 3

A value of TokenElevantionTypeLimited indicates that the user is running with a split token with limited privileges. When elevated the TokenElevationTypeFull value is returned. Non-admin user has a value of TokenElevationTypeDefault.

There is a complete code example for C# at http://www.davidmoore.info/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/

Anders Abel
  • 67,989
  • 17
  • 150
  • 217
  • Link is dead. Is it best to place the sample in the answer? Not sure what convention dictates here, guess it would have to do with licensing if linking a 3rd party? – TheXenocide Jun 29 '18 at 23:42
  • @TheXenocide The sample should have been in the answer (if copyright permits). I've learnt since I wrote this that dying links are a problem. – Anders Abel Jun 30 '18 at 09:23
  • @AndersAbel thanks for the followup; I've only participated in the answering side of the community a little here and there so it's good to know what the "best practices" are. – TheXenocide Jul 02 '18 at 15:01
1

For any VB.NET people (I know you're out there ...), here's a version that I concocted from various sources and is, I think, optimized to determine whether the current user (including elevated) is in a defined Administrators group, machine or domain, with or without UAC enabled. (Lots of credit to other posts here and elsewhere for this one!)

Firstly, it uses a static null-able Boolean to retain the Administrator status because, although the basic check is quick, the full test can take tens of seconds, so you only want to do it once - if at all if you can help it.

Secondly, it errs on the side of the basic test being incorrect/false, which is usually the case if the user is AD-administered or if the local machine has UAC enabled. So if it can decide a user is an Administrator, it will.

Thirdly, you can add or remove criteria from the AuthorizationGroups as you see fit but the ones included cover most situations.

Lastly, if anything goes wrong, you'll get False; if you want an error, you can have one, but personally I don't see the point.

Function IsAdministrator() As Boolean

    Static bResult As Boolean? = Nothing
    Try
        If bResult Is Nothing Then
            bResult = New WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator)
            If Not bResult Then
                Dim oContext As PrincipalContext = Nothing
                Try 'to get a domain context first ...
                    Domain.GetComputerDomain()
                    oContext = New PrincipalContext(ContextType.Domain)
                Catch
                    '... if it fails, fall through to a machine context
                End Try
                If oContext Is Nothing Then oContext = New PrincipalContext(ContextType.Machine)
                Dim oPrincipal As UserPrincipal = UserPrincipal.FindByIdentity(oContext, WindowsIdentity.GetCurrent().Name)
                If oPrincipal IsNot Nothing Then
                    bResult = oPrincipal.GetAuthorizationGroups().Any(Function(p) _
                        p.Sid.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid) OrElse
                        p.Sid.IsWellKnown(WellKnownSidType.AccountDomainAdminsSid) OrElse
                        p.Sid.IsWellKnown(WellKnownSidType.AccountAdministratorSid) OrElse
                        p.Sid.IsWellKnown(WellKnownSidType.AccountEnterpriseAdminsSid))
                End If
            End If
        End If
    Catch
        bResult = False
    End Try
    Return bResult.GetValueOrDefault(False)
End Function
SteveCinq
  • 1,920
  • 1
  • 17
  • 22
0

I know this is old but I've found the below way to work well across all systems. I needed it to work on .net 2 and other solutions such as WinAPI and Management Objects failed on certain versions of Windows:

Launch a new process running the command net localgroup administrators and parse the output appropriately. This works with both UAC enabled and disabled and doesn't need an elevated process.

Adam Short
  • 498
  • 7
  • 28
-6

If you are an Admin, you could temporarily disable UAC from code then re-enable it. The registry key is

Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System Value: EnableLUA Set to: 0 to disable, 1 to enable

So you could do something like

RegistryKey myKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\Policies\\System", true);
myKey.SetValue("EnableLUA", "1", RegistryValueKind.String);

Then check your principal.. It is kindof a hack, but its worth a shot.

Isaac Levin
  • 2,809
  • 9
  • 49
  • 88