Я пытаюсь получить имя пользователя Windows, вошедшего в систему в данный момент, в формате «Джон Доу». Я не уверен, есть ли для этого общепринятый термин, но подумайте, имя, которое вы видите, когда открываете меню «Пуск», а не строку, которую вы пишете для входа в систему.
Я начал с просмотра ответов на этот вопрос, но, похоже, они полностью заняты поиском имени пользователя. Сначала я рассматривал такой обходной путь:
string GetName(string userName) => string.Join(' ', Regex.Split(userName, @"[A-Z]"));
string name = GetName(Environment.UserName);
Но понял, что это не совсем хорошее универсальное решение, поскольку имена пользователей, не соответствующие формату ^[A-Z]([^A-Z]*)[A-Z]([^A-Z]*)$
, будут форматироваться неправильно или вообще не отформатироваться.
GetName("doejohn") // "doejohn"
GetName("RonaldMcDonald") // "Ronald Mc Donald"
Моя следующая остановка была здесь, чтобы посмотреть, смогу ли я найти способ получить значение из системы напрямую, вместо того, чтобы вычислять его самостоятельно, и я продвинулся немного дальше: System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName
казалось именно тем, что я хочу в теории, и хотя это может работать, а может и не работать в других сценариях, в моем, похоже, это не работает, потому что я являюсь частью группы.
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'.
Моя лучшая идея сейчас, хотя я и застрял, — использовать GroupPrincipal
, если UserPrincipal
не работает, но я открыт для других решений, если это неправильно или противоречит передовой практике.
Вы пробовали UserPrincipal.FindByIdentity
передать SID от WindowsIdentity.GetCurrent().USer
?
Этот ответ очень помог мне в решении.
С точки зрения функции мое решение идентично данному ответу. Мои изменения заключаются в следующем:
""
в случае исключения NullReferenceException при назначении userInfo
.Насколько я могу судить, это решение работает независимо от того, является ли пользователь частью группы или нет.
Требуются пакеты NuGet System.DirectoryServices
и System.DirectoryServices.AccountManagement
.
[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 "";
}
Good luck with "Martin Luther King, Jr.", "Ludwig van Beethoven", and "大谷 翔平".
Является ли ваш пользователь/компьютер активным участником AD/AAD или это локальный пользователь?