Question

I've tagged this question with C# because is part of .NET and is known that some people can programming and understand without problems both VB.NET and C# as one, and I should not have problems to translate the C# instructions to VB.NET then I would be happy with a solution written in one of those languages.


I would like to specify an username in this function to retrieve if it's an Admin or not, what changes I should do?

MsgBox(UserIsAdmin("Elektro"))

' ByVal UserName as String or other needed object.
Public Function UserIsAdmin(ByVal UserName As XXXX) As Boolean 

    Dim Identity As Security.Principal.WindowsIdentity =
    Security.Principal.WindowsIdentity.FromUserName(UserName)

    Return New Security.Principal.WindowsPrincipal(Identity).
               IsInRole(Security.Principal.WindowsBuiltInRole.Administrator)

End Function

PS: Ofcourse the FromUserName method does not exist.


UPDATE

I'm just trying @meziantou approach but I always get an exception about the username structure or about the network entry is not found, but, anyways, this is not exactlly what I'm looking for (I mean specify a domain or computername or whatever else that is not done automated by the function).

Public Class Form

Private Sub Test() Handles MyBase.Shown

    ' Things that I've tried:

    MsgBox(UserIsAdmin("Administrador")) ' Username
    MsgBox(UserIsAdmin("Administrador@127.0.0.1")) ' Username@LocalHost
    MsgBox(UserIsAdmin(Security.Principal.WindowsIdentity.GetCurrent().Name)) ' DomainName\Username
    MsgBox(UserIsAdmin("Administrador@ELEKTRO")) ' Username@DomainName
    MsgBox(UserIsAdmin(Security.Principal.WindowsIdentity.GetCurrent.User.Value)) ' The SID

End Sub

''' <summary>
''' Determines whether an user is an Administrator.
''' </summary>
''' <returns><c>true</c> if the user is an Administrator, <c>false</c> otherwise.</returns>
Public Function UserIsAdmin(Optional ByVal UserName As String = String.Empty) As Boolean

    Dim Identity As Security.Principal.WindowsIdentity =
        If(Not String.IsNullOrEmpty(UserName),
           New Security.Principal.WindowsIdentity(UserName),
           Security.Principal.WindowsIdentity.GetCurrent())

    Return New Security.Principal.WindowsPrincipal(Identity).
               IsInRole(Security.Principal.WindowsBuiltInRole.Administrator)

End Function

End Class

UPDATE 2

I'm trying the @Frinavale approach but I'm not able to adapt this code to retrieve the information that I'm interested to.

Imports System.DirectoryServices.AccountManagement
Imports System.Security.Principal

Public Class Form1

    Private Sub Test() Handles MyBase.Shown

        Dim pContext As PrincipalContext = New PrincipalContext(ContextType.Machine)
        Dim pUsers As Principal = New UserPrincipal(pContext)
        Dim pSearcher As PrincipalSearcher = New PrincipalSearcher(pUsers)

        For Each User As Principal In pSearcher.FindAll()

            For Each Group As Principal In User.GetGroups
                ' Result of 'Administrators' (in Spanish): 'Administradores', 
                ' so this is not efficient to compare.
                MsgBox(Group.Name)
            Next

            ' Any of these works:
            ' It throws an exception because 
            ' i'm not passing the expected parameter for a WindowsIdentity.

            MsgBox(UserIsAdmin(User.Name))
            ' MsgBox(UserIsAdmin(User.UserPrincipalName))
            ' MsgBox(UserIsAdmin(User.DistinguishedName))
            ' MsgBox(UserIsAdmin(User.SamAccountName))

        Next User

    End Sub

    Public Function UserIsAdmin(ByVal User As String) As Boolean

        Using Identity As New WindowsIdentity(User)
            Return New WindowsPrincipal(Identity).IsInRole(WindowsBuiltInRole.Administrator)
        End Using

    End Function

End Class
Was it helpful?

Solution

You can use the GroupPrincipal Class to retrieve all users that are part of the administrator group. Once you have all the members, you can determine if the user is in the group by comparing the member's name to the user name provided.

For example:

Public Function UserIsAdmin(ByVal userName As String) As Boolean
        Dim groupName As String = "administrators" '<--You can localize this'
        Dim isAdmin As Boolean
        Using context As PrincipalContext = New PrincipalContext(ContextType.Machine)
            Dim gfilter As GroupPrincipal = GroupPrincipal.FindByIdentity(context, groupName)
            If gfilter IsNot Nothing Then
                Dim members = gfilter.GetMembers
                For Each member In members
                    If String.Compare(member.Name, userName, True) = 0 Then
                        isAdmin = True
                    End If
                Next
            End If
        End Using
        Return isAdmin
End Function

I know that you mentioned that the group's name is localized (which hasn't occurred for me because I'm using an US English operating system/environment). In that case I recommend that you look into the topic of Globalization (store store a localized version of "administrators" into resource files with the key being "administrators" and then retrieve the appropriate text for "administrator" based on the culture that you are working in)

OTHER TIPS

To get a WindowsIdentity from a user name, you can use the WindowsIdentity constructor (http://msdn.microsoft.com/en-us/library/td3046fc(v=vs.110).aspx)

Dim windowsIdentity = New WindowsIdentity("administrator")
New WindowsPrincipal(windowsIdentity).IsInRole(WindowsBuiltInRole.Administrator)

MSDN says that a WindowsIdentity object can be only a logged user, so seems impossible to do the username conversion that I wanted, but, this is a working solution:

' User Is Admin?
'
' Instructions:
' 1. Add a reference to 'System.DirectoryServices.AccountManagement'.
' 2. Imports System.DirectoryServices.AccountManagement
'
' Example Usages:
' MsgBox(UserIsAdmin("Administrador"))
' MsgBox(UserIsAdmin(New Security.Principal.SecurityIdentifier("S-1-5-21-250596608-219436059-1115792336-500")))
'
''' <summary>
''' Determines whether an User is an Administrator, in the current machine.
''' </summary>
''' <param name="UserName">Indicates the account Username.</param>
''' <returns><c>true</c> if user is an Administrator, <c>false</c> otherwise.</returns>
Public Function UserIsAdmin(ByVal UserName As String) As Boolean

    Dim AdminGroupSID As New SecurityIdentifier("S-1-5-32-544")

    Dim pContext As New PrincipalContext(ContextType.Machine)
    Dim pUser As New UserPrincipal(pContext)
    Dim pSearcher As New PrincipalSearcher(pUser)

    Dim User As Principal =
        (From u As Principal In pSearcher.FindAll
        Where u.Name.Equals(UserName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault

    If User Is Nothing Then
        Throw New Exception(String.Format("User with name '{0}' not found.", UserName))
    End If

    Dim IsAdmin As Boolean =
        (From Group As GroupPrincipal In User.GetGroups
         Where Group.Sid = AdminGroupSID).Any

    pContext.Dispose()
    pSearcher.Dispose()
    pUser.Dispose()

    Return IsAdmin

End Function
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top