简体   繁体   中英

Get Windows username containing non-english chars in c#

We use the code from this post to get the name of the connected windows user in order to disconnect them.

In brief, GetUserName(), GetCurrentUserName(), LogOffUser() and LogOffCurrentUser(), as follows.

THE PROBLEM: Under english version of Windows and when the username contains non-english characters, the user will not logoff.

After some debugging we found out that the username inside GetUserName() is displayed with question marks instead of the non-enlgish characters, but in LogOffCurrentUser() is displayed properly. So the user stays connected because the username cannot be found when attempting to disconnect.

Is there any way to solve this?

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);
    }

THE SOLUTION:

When trying to fetch windows usernames that contain non-english (non-latin) characters you must p/invoke the unicode version of WTSQuerySessionInformation which is WTSQuerySessionInformationW .

Then the username can be placed to a string using Marshal.PtrToStringUni or Marshal.PtrToStringAuto .

In that way WTSLogoffSession will find the username in session dictionary and disconnect the user properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM