0

I am writing a Visual Basic .NET desktop application (currently using WinForms and .NET Framework 4.5.1).

I need the application to detect whether the current windows user has the system Administrator role, but without needing the user to start the application using Run as administrator.

  1. I have the Administrator role on the Windows 10 machine that I am logged in to.

enter image description here

  1. The following code returns machinename/ian

    Dim CurrUser As WindowsIdentity CurrUser = WindowsIdentity.GetCurrent() MsgBox(CurrUser.Name)

  2. However, when I test whether I have the administrator role, the result is False unless I Run as administrator

    MsgBox(My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator))

Similar questions have been asked a number of times on SO, but the solutions (all similar to the above) return false unless I start the app using Run as Administrator.

Motivation

  • The application will be used by different users on the machine that it is installed on
  • I'd like to hide an extended set of options from the general user, but make them available to the 'owner' of the machine, who I identify as being a user with the Administrators role
  • The app itself does not need to be executed with elevated permissions - it should not have the ability to change parts of the user's system. From a trust perspective, I would like my users to know that the app is not dangerous and they do not need to Run as administrator for no good reason.

I'm looking for a solution that will work just as well on Windows 10 Home (which I believe doesn't have Directory Services and Active Directory?), preferably the solution will also work on Windows 7.

isedwards
  • 2,429
  • 21
  • 29
  • 1
    What would you do with the information? It seems to me that at the moment when you ask, the answer is more or less accurate, because you need to go through UAC before you can do anything administrator-y. – Craig Aug 24 '17 at 20:48
  • 1
    The related question here has an answer with information on looking up group membership through directory services, which I would expect to be accurate on an absolute basis rather than in the context of current execution: https://stackoverflow.com/questions/52256/how-to-check-if-a-given-user-is-a-member-of-the-built-in-administrators-group?rq=1 – Craig Aug 24 '17 at 20:51
  • @Craig - I've updated my question with a section on "motivation" (why I'm trying to do this). I'll take a look at directory services. Ideally, the solution will work on Windows 7 and Vista as well as Windows 10. – isedwards Aug 25 '17 at 06:42
  • If you're not going to *actually* force a UAC prompt then it means that those settings/preferences are *actually* editable by everyone, you're just trying to hide the (most direct) means of doing so from non-admins. This in turn may give people a *false* sense of security about those settings. I'd seriously question whether it's worth doing versus *actually* protecting the settings using the built in windows controls. – Damien_The_Unbeliever Aug 25 '17 at 07:02
  • Thanks @Damien - I've updated the motivation again to reflect your comments. The key issue for me is that I really **don't want my app to run as administrator**, I anticipate that it will be shared a lot on memory sticks and the risk is that it could potentially pick up malware, viruses etc. – isedwards Aug 25 '17 at 07:44
  • 1
    [how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on](http://www.davidmoore.info/blog/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/) seems to have a C# version that assumes that if it sees a split token the user is an admin. Shouldn't be too tricky to translate to VB.Net. – Damien_The_Unbeliever Aug 25 '17 at 09:14

1 Answers1

0

CAUTION: The check used below for testing whether a user is an Administrator is not 100% reliable, see the discussion in "User Account Control (UAC)" section of the link below and the references.


The code below is based on the C# solution found here (suggested in this comment by @Damien_The_Unbeliever)

Imports System.Runtime.InteropServices
Imports System.Security.Principal

<DllImport("advapi32.dll", SetLastError:=True)>
Private Shared Function GetTokenInformation(tokenHandle As IntPtr, tokenInformationClass As TokenInformationClass, tokenInformation As IntPtr, tokenInformationLength As Integer, ByRef returnLength As Integer) As Boolean
End Function

''' <summary>
''' Passed to <see cref="GetTokenInformation"/> to specify what
''' information about the token to return.
''' </summary>
Private 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
End Enum

''' <summary>
''' The elevation type for a user token.
''' </summary>
Private Enum TokenElevationType
    TokenElevationTypeDefault = 1
    TokenElevationTypeFull
    TokenElevationTypeLimited
End Enum




Private Function IsAdmin()
    Dim identity = WindowsIdentity.GetCurrent()
    If identity Is Nothing Then
        Throw New InvalidOperationException("Couldn't get the current user identity")
    End If
    Dim 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) Then
        Return True
    End If

    ' If we're not running in Vista onwards, we don't have to worry about checking for UAC.
    If Environment.OSVersion.Platform <> PlatformID.Win32NT OrElse Environment.OSVersion.Version.Major < 6 Then
        ' Operating system does not support UAC; skipping elevation check.
        Return False
    End If

    Dim tokenInfLength As Integer = Marshal.SizeOf(GetType(Integer))
    Dim tokenInformation As IntPtr = Marshal.AllocHGlobal(tokenInfLength)

    Try
        Dim token = identity.Token
        Dim result = GetTokenInformation(token, TokenInformationClass.TokenElevationType, tokenInformation, tokenInfLength, tokenInfLength)

        If Not result Then
            Dim exception = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())
            Throw New InvalidOperationException("Couldn't get token information", exception)
        End If

        Dim elevationType = DirectCast(Marshal.ReadInt32(tokenInformation), TokenElevationType)

        Select Case 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
            Case Else
                ' Unknown token elevation type.
                Return False
        End Select
    Finally
        If tokenInformation <> IntPtr.Zero Then
            Marshal.FreeHGlobal(tokenInformation)
        End If
    End Try
End Function
Community
  • 1
  • 1
isedwards
  • 2,429
  • 21
  • 29
  • The link is dead, but can still be reached via archive.org: http://web.archive.org/web/20170808080413/http://www.davidmoore.info/blog/2011/06/20/how-to-check-if-the-current-user-is-an-administrator-even-if-uac-is-on/ – rabejens May 07 '18 at 08:52