获取当前用户的全名,返回一个空字符串(C#/C++)
Posted
技术标签:
【中文标题】获取当前用户的全名,返回一个空字符串(C#/C++)【英文标题】:Getting the full-name of the current user, returns an empty string (C#/C++) 【发布时间】:2010-06-07 14:27:35 【问题描述】:我尝试获取当前登录用户的全名(全名,而不是用户名)。
以下代码 C#、C++ 工作正常,但在未连接到网络的 XP 计算机上,如果我在登录后约 20 分钟运行它会得到空字符串(它在第一个 ~20 分钟后运行正常登录)
使用 Win32 API (GetUserNameEx) 而不是 PrincipalContext,因为 PrincipalContext 在离线工作时可能需要长达 15 秒。
任何帮助,为什么我得到一个空字符串作为结果虽然指定了用户全名???
- C#代码
public static string CurrentUserFullName
get
const int EXTENDED_NAME_FORMAT_NAME_DISPLAY = 3;
StringBuilder userName = new StringBuilder(256);
uint length = (uint) userName.Capacity;
string ret;
if (GetUserNameEx(EXTENDED_NAME_FORMAT_NAME_DISPLAY, userName, ref length))
ret = userName.ToString();
else
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception("GetUserNameEx Failed. Error code - " + errorCode);
return ret;
[DllImport("Secur32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetUserNameEx(int nameFormat, StringBuilder lpNameBuffer, ref uint lpnSize);
- C++ 代码
#include "stdafx.h"
#include <windows.h>
#define SECURITY_WIN32
#include <Security.h>
#pragma comment( lib, "Secur32.lib" )
int _tmain(int argc, _TCHAR* argv[])
char szName[100];
ULONG nChars = sizeof( szName );
if ( GetUserNameEx( NameDisplay, szName, &nChars ) )
printf( "Name: %s\n", szName);
else
printf( "Failed to GetUserNameEx\n" );
printf( "%d\n", GetLastError() );
return 0;
【问题讨论】:
【参考方案1】:函数GetUserNameEx
和NameDisplay
不能在离线模式下工作。仅当计算机在线时才能访问此信息。我建议您实现一些信息缓存,例如全名或其他只能在在线模式下访问的信息。例如,如果计算机在线,您可以检索和保存完整用户名等信息。因此,您可以在注册表中的某些配置文件中包含用户 SID 与其全名之间的映射。如果您不能直接提供全名,您可以从现金中获取信息。
Windows 有许多不同的通知(如NotifyAddrChange
),您可以使用(如果需要)监控从在线模式到离线模式的变化。
您可以从LsaGetLogonSessionData
和WTSQuerySessionInformation
API(GetUserNameEx
你已经知道)获得有关当前用户会话的大多数信息(也可以在离线模式下),但您不会在其中找到完整的用户名。
如果您确实找到了在离线模式下获取用户全名的方法,请将信息发布给我。
【讨论】:
问题是我的站可能一直离线。在 C# 中,您可以使用 UserPrincipal.Current.DisplayName (UserPrincipal namespace: System.DirectoryServices.AccountManagement) 轻松获取完整的用户名(无论您的站点是否连接到网络)。问题是此调用可能需要 5 -15 秒断开连接,这对我来说太多了(我可以第一次缓存它,但第一次调用仍然是 10 秒太多了) @Nir:对我来说,UserPrincipal.Current.DisplayName 在断开连接的站点上抛出 PrincipalServerDownException。【参考方案2】:尝试使用 GetUserNameExA(用于 ASCII)而不是 GetUserNameEx 宏。它有帮助吗?也打印程序的输出。
【讨论】:
我刚试过。 GetUserNameExA 的 GetUserNameEx 结果相同。我打印了错误代码 1332,这意味着“没有完成帐户名称和安全 ID 之间的映射”。但是,为当前用户指定了一个全名,并且在登录后约 20 分钟开始返回有效结果。它因未知原因停止工作(我搜索了病毒,禁用了屏幕保护程序以及任何其他可能在这 20 分钟内出现问题的东西......)【参考方案3】:我很好奇:对于“永久离线”站,用户名存储在哪里(在操作系统中)?通过浏览控制面板用户,看起来本地用户帐户没有地方存储“名称显示”,只有一个用户名。
未连接节点的数据存储在哪里对我来说是个谜。如果(实际上)数据只存储在域控制器中,我唯一能想到的就是如前所述缓存信息。
【讨论】:
【参考方案4】:所以使用第一个,检查结果,然后通过异步委托调用第二个。您的应用不会有任何延迟,而且全名肯定不是它的核心功能 - 我希望 :-)
【讨论】:
【参考方案5】:请尝试在您的计算机上禁用 UAC。我想它应该在那之后工作。
禁用它的步骤。
-
转到控制面板。
然后发给用户。
选择您要保留的管理员帐户。
删除您不希望拥有的具有管理员权限的帐户。
如果将来您想创建任何具有管理员权限的新帐户,您可以创建一个帐户并使用更改帐户类型将其设为管理员帐户。
【讨论】:
以上是关于获取当前用户的全名,返回一个空字符串(C#/C++)的主要内容,如果未能解决你的问题,请参考以下文章
调用 ASP.Net WebAPI 端点时,JavaScript 获取调用返回空字符串