Click here to Skip to main content
15,881,172 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am trying to get a username from a sessionid.

I copied the vb.net signatures from pinvoke.net: WTSQuerySessionInformation (wtsapi32)[^] and pinvoke.net: WTSInfoClass (Enums)[^]

Then I used the C# code for How to retrieve username by session id from the WTSQuerySessionInformation page as a reference to write it in vb.net and came up with this function:
Private Shared Function GetUserName(sessionID As Integer)
    Dim Buffer As IntPtr
    Dim Count As Integer
    Dim UserName As String
    WTSQuerySessionInformation(IntPtr.Zero, sessionID, WTS_INFO_CLASS.WTSUserName, Buffer, Count)
    UserName = Marshal.PtrToStringAnsi(Buffer)

    WTSFreeMemory(Buffer)
    Return UserName
End Function


When I run it with the sessionid of -1 I am only getting the first letter of the username. If I change this line from UserName = Marshal.PtrToStringAnsi(Buffer) to UserName = Marshal.PtrToStringAuto(Buffer) then it works. What gives and how to fix it to use Marshal.PtrToStringAnsi?

What I have tried:

The C# code from pinvoke.net: WTSQuerySessionInformation (wtsapi32)[^] works fine.
Posted
Updated 17-Apr-20 4:07am

Your VB code doesn't resemble the code you link to.
Try this:
VB
Public Shared Function GetUsernameBySessionId(ByVal sessionId As Integer) As String
    Dim buffer As IntPtr
    Dim strLen As Integer
    Dim username = "SYSTEM"

    If WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSUserName, buffer, strLen) AndAlso strLen > 1 Then
        username = Marshal.PtrToStringAnsi(buffer)
        WTSFreeMemory(buffer)

        If WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSDomainName, buffer, strLen) AndAlso strLen > 1 Then
            username = Marshal.PtrToStringAnsi(buffer) & "\" & username
            WTSFreeMemory(buffer)
        End If
    End If

    Return username
End Function
Note the nested If which does a second fetch from the Domain, and the preset value for username
 
Share this answer
 
Did you try using Marshall.PtrToStringUni? I can't tell whether you are calling WTSQuerySessionInformationA or WTSQuerySessionInformationW. Look at the memory pointed to by that IntPtr in your debugger to see what you're actually getting back from the API call.
 
Share this answer
 
Comments
Member 14623989 17-Apr-20 11:17am    
Looks like the one in the article was for WTSQuerySessionInformationW. Using Marshall.PtrToStringUni worked though. I tried looking at the memory pointed to by that IntPtr, but I don't see the reason why. I only started using VS this month. Thanks!
JudyL_MD 17-Apr-20 11:29am    
For English at least, unicode will show in a memory area as a recognizable ascii character followed by a byte of 0, then another character and another 0. Unicode is a 2-byte encoding and for those languages that don't need the upper byte, the 2nd byte is always a 0. It's pretty distinctive-looking in memory ... char 00 char 00 char 00
@OriginalGriff - Sorry, I oversimplified it in my code above. With the code you provided I'm getting the same thing. I get 1 character for the domain name and 1 character for my username. I just don't understand why.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900