I'm trying to get the name of the currently logged in Windows user in the format "John Doe". I'm not sure if there's an accepted term for this, but think, the name you see when you bring up the start menu, as opposed to the string you write to sign in.
I started with looking through the answers on this question, but they seem to be entirely concerned with finding the user's login name. At first I considered a work-around like this:
string GetName(string userName) => string.Join(' ', Regex.Split(userName, @"[A-Z]"));
string name = GetName(Environment.UserName);
But realised that this isn't really a good one-size-fits-all solution, as usernames that are not in the format ^[A-Z]([^A-Z]*)[A-Z]([^A-Z]*)$
would format wrongly or not at all.
GetName("doejohn") // "doejohn"
GetName("RonaldMcDonald") // "Ronald Mc Donald"
My next stop was here to see if I could find how to get the value from the system directly instead of computing it myself, and I got a decent bit further: System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName
seemed to be exactly what I want in theory, and while this may or may not work in other scenarios, it doesn't seem to work in mine due to being part of a group.
var name1 = System.Security.Principal.WindowsIdentity.GetCurrent().Name; // "AzureAD\JohnDoe"
var name2 = UserPrincipal.Current.DisplayName;
// System.Exception:
// Unable to cast object of type 'System.DirectoryServices.AccountManagement.GroupPrincipal'
// to type 'System.DirectoryServices.AccountManagement.UserPrincipal'.
My best idea now, though I've hit a wall, is using GroupPrincipal
if UserPrincipal
fails, but I'm open to other solutions if that's wrong or against best practice.
This answer was hugely helpful in my solution.
In terms of function, my solution is identical to the given answer. My changes are as follows:
""
in the event of a NullReferenceException while assigning to userInfo
As far as I can tell, this solution works regardless of whether the user is part of a group or not.
Requires System.DirectoryServices
and System.DirectoryServices.AccountManagement
NuGet packages.
[DllImport("secur32.dll", CharSet = CharSet.Auto)]
private static extern int GetUserNameEx(int nameFormat, StringBuilder userName, ref uint userNameSize);
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern int NetUserGetInfo([MarshalAs(UnmanagedType.LPWStr)] string serverName,
[MarshalAs(UnmanagedType.LPWStr)] string userName,
int level, out IntPtr bufPtr);
[DllImport("netapi32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern long NetApiBufferFree(out IntPtr bufPtr);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct USER_INFO_10
{
[MarshalAs(UnmanagedType.LPWStr)] public string usri10_name;
[MarshalAs(UnmanagedType.LPWStr)] public string usri10_comment;
[MarshalAs(UnmanagedType.LPWStr)] public string usri10_usr_comment;
[MarshalAs(UnmanagedType.LPWStr)] public string usri10_full_name;
}
[GeneratedRegex(@"(\S+), (\S+)", options: RegexOptions.Compiled)]
private static partial Regex LastnameFirstnameToFirstnameLastnameRegex();
[GeneratedRegex(@"(.+)\\.+", options: RegexOptions.Compiled)]
private static partial Regex DomainExtractorRegex();
[GeneratedRegex(@".+\\(.+)", options: RegexOptions.Compiled)]
private static partial Regex NameExtractorRegex();
private static string GetUserFullName()
{
var username = new StringBuilder(1024);
uint userNameSize = (uint)username.Capacity;
// try to get display name and convert from "Last, First" to "First Last" if necessary
if (0 != GetUserNameEx(3, username, ref userNameSize))
return LastnameFirstnameToFirstnameLastnameRegex().Replace(username.ToString(), "$2 $1");
// get SAM compatible name <server/machine>\\<username>
if (0 == GetUserNameEx(2, username, ref userNameSize)) return "";
IntPtr bufPtr;
try
{
string domain = DomainExtractorRegex().Replace(username.ToString(), @"$1");
DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
DomainController dc = DomainController.FindOne(context);
if (0 == NetUserGetInfo(dc.IPAddress,
NameExtractorRegex().Replace(username.ToString(), "$1"),
10, out bufPtr))
{
try
{
var userInfo = (USER_INFO_10)Marshal.PtrToStructure(bufPtr, typeof(USER_INFO_10));
return LastnameFirstnameToFirstnameLastnameRegex().Replace(userInfo.usri10_full_name, "$2 $1");
}
catch (NullReferenceException)
{
return "";
}
}
}
finally
{
NetApiBufferFree(out bufPtr);
}
return "";
}