我发现在 Windows 7 64 位上,在一台有域名的机器上,GetUserNameEx( 3, .... ) 应该将扩展名称格式 DisplayName (==3) 放入缓冲区,工作正常.
但是,它不适用于 Windows 7 32 位,虚拟机在工作组上,而不是在域上,它返回 ERROR_NONE_MAPPED。
例如,您如何以适用于 Windows 的方式阅读此人的友好名称“Fred Smith”? GetUserNameEx 显然已损坏。有人告诉我,实际上,并没有坏,只是不打算为不在域中的用户工作。我想知道为什么不存在本地 SAM 信息?而且似乎没有其他直接的 API 可以执行此操作。
如果 Windows 为您提供 ERROR_NONE_MAPPED,则您不走运,并且可能不在域中。所以这并不是 API 的友好区域。
[看起来有可能调用 NetUserGetInfo,读取本地 SAM 信息,当不在域上时,但您需要先知道用户名和密码,然后它可能会查找友好的姓名。]
最佳答案
这是移植到 C# 的 Warren 解决方案。我添加了从域名中检索域 Controller 的 IP,因为至少在我的域中,只使用 \\<domain>
因为服务器名称无效。
using System;
using System.Text;
using System.Net;
using System.Runtime.InteropServices;
using System.DirectoryServices.ActiveDirectory;
[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;
}
private string getUserDisplayName ()
{
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 Regex.Replace(username.ToString(), @"(\S+), (\S+)", "$2 $1");
// 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);
}
}
return String.Empty;
}
关于c# - 您如何在所有版本的 Windows 上可靠地读取用户的显示(名字和姓氏)名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3686201/