War*_* P 4 c# delphi winapi msdn
我发现在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信息,当不在域上时,但您需要首先知道用户名和密码,然后它可能会查找友好名称.]
这是Warren的解决方案移植到C#.我添加了从域名中检索域控制器的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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3428 次 |
最近记录: |