Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A reliable way to obtain the Windows user display name

I need to get the Display Name of the current user, and cannot find a solution that always works. Just for clarity, I'm not looking for the username. I need the "John Doe". The value displayed on the Start Menu.

There are many posts about this question however none have solved my problem.

Get Windows User Display Name

How do I get the AD Display Name of the currently logged in user

These two posts lead me to:

PrincipalContext context = domain.Equals(Environment.MachineName, StringComparison.CurrentCultureIgnoreCase) ?
    new PrincipalContext(ContextType.Machine) :
    new PrincipalContext(ContextType.Domain, domain);

UserPrincipal userPrincipal = new UserPrincipal(context) { SamAccountName = username };
PrincipalSearcher searcher = new PrincipalSearcher(userPrincipal);
userPrincipal = searcher.FindOne() as UserPrincipal;

string displayName = userPrincipal.DisplayName;

And this code works for the most part. However if the user's has disabled/stopped the Server service on his/her computer I get an exception saying "The Server service is not started."

System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName

Same error.

How to get logged-in user's full name in windows?

StringBuilder name = new StringBuilder(1024);
uint userNameSize = (uint)name.Capacity;
const int NameDisplay = 3;
GetUserNameEx(NameDisplay, name, ref userNameSize)

Returns no error, but an empty string if the user is not on a domain.

How do you read the user's display (first and last) name on all versions of Windows reliably?

// get SAM compatible name <server/machine>\\<username>
if (0 != GetUserNameEx(2, username, ref userNameSize))
{
    IntPtr bufPtr;
    try
    {
        string domain = Regex.Replace(username.ToString(), @"(.+)\\.+", @"$1");
        DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
        DomainController dc = DomainController.FindOne(context);

        if (0 == NetUserGetInfo(dc.IPAddress,
                   Regex.Replace(username.ToString(), @".+\\(.+)", "$1"),
                   10, out bufPtr))
        {
            var userInfo = (USER_INFO_10) Marshal.PtrToStructure(bufPtr, typeof (USER_INFO_10));
            return Regex.Replace(userInfo.usri10_full_name, @"(\S+), (\S+)", "$2 $1");
        }
    }
    finally
    {
        NetApiBufferFree(out bufPtr);
    }
}

With the above I get an ActiveDirectoryObjectNotFoundException with message "Domain controller not found in the domain.." when DomainController.FindOne is called.

I haven't found a registry setting for the display name.

I'm don't know what else to try. Please help.

like image 203
Dan Vogel Avatar asked Jan 16 '15 20:01

Dan Vogel


1 Answers

All of the above methods will only work if you are on a domain. If you are not, then you must rely on the local user account store. The following details how to retrieve this info: How can I get a list Local Windows Users (Only the Users that appear in the windows Logon Screen). In a domain situation though, the users account will not be in the local store.

If you are on a domain but not connected to the domain controller, the Display Name will not be readily available to you. This information is stored on the domain controller, not the local user's computer. If your users are on a domain, they really shouldn't be able to disable the Server service(use GPOs). Also, they lose much more than the ability to retrieve their user account by disabling that service.

I would check for domain availability before trying to get the display name. If it fails, display a message indicating the failure. There are potentially too many edges cases here to make it work accounting for all of them. Go with the scenario that you intend the program to be used under, and give an error message for the others.

like image 126
Lee Harrison Avatar answered Oct 16 '22 13:10

Lee Harrison