Netplwiz如何获取邮箱格式用户名?当前登录用户相关技术问询
解答:获取邮箱格式的Windows用户名
Netplwiz的实现逻辑
Netplwiz并非依赖.NET的WindowsIdentity类,而是直接调用Windows底层的安全与账户管理API:它会通过本地安全授权子系统(LSASS) 读取用户对象的用户主体名称(UPN) 属性,或者针对域用户直接查询Active Directory(AD)的userPrincipalName字段,以此拿到邮箱格式的用户名,而非常规的DOMAIN\UserName SAM账户格式。
对当前登录用户实现该功能的方法
可以通过.NET类库或者原生Win32 API两种方式实现,以下是具体方案:
1. .NET类库实现(推荐)
方式一:使用AccountManagement命名空间(简化版)
这个命名空间封装了AD和本地账户的操作逻辑,能直接获取UPN:
using System.DirectoryServices.AccountManagement; public string GetCurrentUserUpn() { // 本地用户用ContextType.Machine,域用户用ContextType.Domain using var context = new PrincipalContext(ContextType.Domain); using var currentUser = UserPrincipal.Current; return currentUser.UserPrincipalName; // 返回xxx@domain.com格式的用户名 }
注意:本地账户需要Windows 10/11及以上版本,且已正确设置UPN属性才能返回对应值。
方式二:直接查询Active Directory(域用户专用)
如果需要更精细的控制,可以通过LDAP查询AD获取用户的UPN:
using System.DirectoryServices; public string GetCurrentUserUpnFromAd() { var currentSamName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; var splitName = currentSamName.Split('\\'); var domain = splitName[0]; var samAccountName = splitName[1]; using var adEntry = new DirectoryEntry($"LDAP://{domain}"); using var searcher = new DirectorySearcher(adEntry) { Filter = $"(&(objectClass=user)(sAMAccountName={samAccountName}))", PropertiesToLoad = { "userPrincipalName" } }; var result = searcher.FindOne(); return result?.Properties["userPrincipalName"][0]?.ToString(); }
2. 原生Win32 API实现(底层方案)
如果需要更贴近Netplwiz的底层逻辑,可以调用Win32 API,比如NetUserGetInfo(获取本地/域用户信息):
using System; using System.Runtime.InteropServices; public static class Win32UserApi { [DllImport("netapi32.dll", CharSet = CharSet.Unicode)] private static extern int NetUserGetInfo(string serverName, string userName, int infoLevel, out IntPtr bufferPtr); [DllImport("netapi32.dll")] private static extern void NetApiBufferFree(IntPtr bufferPtr); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct USER_INFO_10 { public string usri10_name; public string usri10_comment; public string usri10_user_comment; public string usri10_full_name; public string usri10_user_principal_name; // 其他字段按需定义,此处仅保留关键属性 } public static string GetUserUpn(string userName) { IntPtr buffer = IntPtr.Zero; try { // infoLevel=10 表示获取包含UPN的用户信息 var resultCode = NetUserGetInfo(null, userName, 10, out buffer); if (resultCode == 0) { var userInfo = Marshal.PtrToStructure<USER_INFO_10>(buffer); return userInfo.usri10_user_principal_name; } return null; } finally { if (buffer != IntPtr.Zero) NetApiBufferFree(buffer); } } } // 调用示例: var currentSamName = System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\')[1]; var upn = Win32UserApi.GetUserUpn(currentSamName);
可用的关键类、方法与字段
.NET生态
UserPrincipal(System.DirectoryServices.AccountManagement):UserPrincipalName属性直接返回用户的UPN。DirectorySearcher(System.DirectoryServices):通过LDAP查询AD用户的userPrincipalName属性。WindowsIdentity(System.Security.Principal):虽然Name返回SAM格式,但可用于提取当前用户的SID或SAM账户名,作为后续查询的基础。
原生Win32 API
NetUserGetInfo:指定infoLevel=10时可获取包含UPN的用户详细信息。DsGetUserPrincipalName:直接通过用户SID或SAM账户名获取UPN。LsaGetLogonSessionData:获取当前登录会话的完整数据,其中包含用户的UPN信息。
内容的提问来源于stack exchange,提问作者Marc George
相关产品推荐
相关产品推荐

