在 C# 中获取 Windows 包含非英文字符的用户名
Get Windows username containing non-english chars in c#
我们使用 this post 中的代码获取已连接 windows 用户的名称,以便断开他们的连接。
简而言之,GetUserName()、GetCurrentUserName()、LogOffUser()和LogOffCurrentUser(),如下。
问题:
英文版Windows下,当用户名包含非英文字符时,用户不会下线。
调试后发现GetUserName()中的用户名显示为问号而不是非英文字符,但LogOffCurrentUser()中显示正确。因此用户保持连接状态,因为在尝试断开连接时找不到用户名。
有什么办法可以解决吗?
public static string GetUserName(int sessionId, IntPtr server)
{
IntPtr buffer = IntPtr.Zero;
uint count = 0;
string userName = string.Empty;
try
{
WTSQuerySessionInformation(server, sessionId, WTS_INFO_CLASS.WTSUserName, out buffer, out count);
userName = Marshal.PtrToStringAnsi(buffer).ToUpper().Trim();
}
finally
{
WTSFreeMemory(buffer);
}
return userName;
}
//-------------------------------------
public static string GetCurrentUserName()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem");
ManagementObjectCollection collection = searcher.Get();
string username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
string[] parts = username.Split(new char[] { '\' });
if (parts[parts.Length - 1] == "SYSTEM") parts[parts.Length - 1] = "";
return parts[parts.Length - 1];
}
//-------------------------------------
public static bool LogOffUser(string userName, IntPtr server)
{
userName = userName.Trim().ToUpper();
List<int> sessions = GetSessionIDs(server);
Dictionary<string, int> userSessionDictionary = GetUserSessionDictionary(server, sessions);
if (userSessionDictionary.ContainsKey(userName))
{
return WTSLogoffSession(server, userSessionDictionary[userName], false);
}
else
{
return false;
}
}
//-------------------------------------
public static void LogOffCurrentUser()
{
LogOffUser(GetCurrentUserName(), IntPtr.Zero);
}
解决方案:
当尝试获取 windows 包含非英语(非拉丁)字符的用户名时,您必须 p/invoke WTSQuerySessionInformation 的 unicode 版本,即 WTSQuerySessionInformationW.
然后可以使用Marshal.PtrToStringUni或Marshal.PtrToStringAuto.[=10将用户名放入字符串中=]
这样 WTSLogoffSession 将在会话字典中找到用户名并正确断开用户连接。
我们使用 this post 中的代码获取已连接 windows 用户的名称,以便断开他们的连接。
简而言之,GetUserName()、GetCurrentUserName()、LogOffUser()和LogOffCurrentUser(),如下。
问题: 英文版Windows下,当用户名包含非英文字符时,用户不会下线。
调试后发现GetUserName()中的用户名显示为问号而不是非英文字符,但LogOffCurrentUser()中显示正确。因此用户保持连接状态,因为在尝试断开连接时找不到用户名。
有什么办法可以解决吗?
public static string GetUserName(int sessionId, IntPtr server)
{
IntPtr buffer = IntPtr.Zero;
uint count = 0;
string userName = string.Empty;
try
{
WTSQuerySessionInformation(server, sessionId, WTS_INFO_CLASS.WTSUserName, out buffer, out count);
userName = Marshal.PtrToStringAnsi(buffer).ToUpper().Trim();
}
finally
{
WTSFreeMemory(buffer);
}
return userName;
}
//-------------------------------------
public static string GetCurrentUserName()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem");
ManagementObjectCollection collection = searcher.Get();
string username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
string[] parts = username.Split(new char[] { '\' });
if (parts[parts.Length - 1] == "SYSTEM") parts[parts.Length - 1] = "";
return parts[parts.Length - 1];
}
//-------------------------------------
public static bool LogOffUser(string userName, IntPtr server)
{
userName = userName.Trim().ToUpper();
List<int> sessions = GetSessionIDs(server);
Dictionary<string, int> userSessionDictionary = GetUserSessionDictionary(server, sessions);
if (userSessionDictionary.ContainsKey(userName))
{
return WTSLogoffSession(server, userSessionDictionary[userName], false);
}
else
{
return false;
}
}
//-------------------------------------
public static void LogOffCurrentUser()
{
LogOffUser(GetCurrentUserName(), IntPtr.Zero);
}
解决方案:
当尝试获取 windows 包含非英语(非拉丁)字符的用户名时,您必须 p/invoke WTSQuerySessionInformation 的 unicode 版本,即 WTSQuerySessionInformationW.
然后可以使用Marshal.PtrToStringUni或Marshal.PtrToStringAuto.[=10将用户名放入字符串中=]
这样 WTSLogoffSession 将在会话字典中找到用户名并正确断开用户连接。