可靠的方法获取Windows用户显示名称

9
我需要获取当前用户的显示名称,但找不到总是有效的解决方案。仅为了明确起见,我不是在寻找用户名。我需要“约翰·多伊”。开始菜单上显示的值。
有很多关于这个问题的帖子,但没有一个解决了我的问题。 获取 Windows 用户显示名称 如何获取当前登录用户的 AD 显示名称 这两篇文章引导我到:
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;

这段代码大部分情况下是可行的。然而,如果用户停用/停止了计算机上的服务器服务,我会收到一个异常,显示“服务器服务未启动”。

System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName

同样的错误。

如何在Windows中获取已登录用户的全名?

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

如果用户不在域上,则返回无错误但空字符串。 如何可靠地在所有版本的Windows上读取用户的显示(名字和姓氏)?
// 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);
    }
}

当调用DomainController.FindOne时,我遇到了ActiveDirectoryObjectNotFoundException错误,提示“在该域中找不到域控制器..”。

我没有找到显示名称的注册表设置。

我不知道还有什么其他方法可尝试。请帮忙。


1
我不知道你是否能找到一个100%的解决方案;但是,对于一些分支情况(例如用户不在域上),你看到了什么概率呢?如果影响只有几个用户,那么付出的努力可能就不值得了。 - Brian Driscoll
1个回答

6
以上所有方法只适用于域环境。如果不是,则必须依赖本地用户帐户存储。以下是如何检索此信息的详细信息:参见如何获取本地Windows用户列表(仅显示在Windows登录屏幕上的用户)。然而,在域情况下,用户帐户将不在本地存储中。
如果您在域中但未连接到域控制器,则Display Name对您不可用。此信息存储在域控制器上,而不是本地用户计算机上。如果您的用户在域中,则真的不应该能够禁用服务器服务(使用GPO)。此外,他们失去了比仅仅无法检索其用户帐户更多的东西。
在尝试获取显示名称之前,我建议您先检查域可用性。如果失败,请显示指示失败的消息。这里有太多的边缘情况,无法考虑所有情况。按照预期程序运行的场景进行,并为其他场景提供错误消息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接