Jump to content

ListUserSessions


argumentum
 Share

Recommended Posts

..was looking for UserName from SessionID so I put this together

#include <Debug.au3> ; for _DebugArrayDisplay()

; all you can get from _WTSQuerySessionInformation()
Global $i = _WTSQuerySessionInformation(-1, 4) ; current user's SessionId
Global $__a_WTS_INFO_CLASS = StringSplit("WTSInitialProgram,WTSApplicationName,WTSWorkingDirectory,WTSOEMId,WTSSessionId,WTSUserName," & _
"WTSWinStationName,WTSDomainName,WTSConnectState,WTSClientBuildNumber,WTSClientName,WTSClientDirectory,WTSClientProductId,WTSClientHardwareId," & _
"WTSClientAddress,WTSClientDisplay,WTSClientProtocolType,WTSIdleTime,WTSLogonTime,WTSIncomingBytes,WTSOutgoingBytes,WTSIncomingFrames," & _
"WTSOutgoingFrames,WTSClientInfo,WTSSessionInfo,WTSSessionInfoEx,WTSConfigInfo,WTSValidationInfo,WTSSessionAddressV4,WTSIsRemoteSession", ",", 2)
For $n = 0 To UBound($__a_WTS_INFO_CLASS) -1
    ConsoleWrite($n & @TAB & StringLeft($__a_WTS_INFO_CLASS[$n] & ' ________________', 24) & " " & _WTSQuerySessionInformation($i, $n, 1) & @CRLF)
Next

Global $a = ListUserSessions()
_DebugArrayDisplay($a, "ListUserSessions()")

Func ListUserSessions() ; mod. of https://www.autoitscript.com/forum/topic/139774-dllcall-and-returned-pointers/?do=findComment&comment=980850
    Local $_Self_SessionId = _WTSQuerySessionInformation(-1, 4) ; -1 = current user ; 4 = WTSSessionId
    Local Enum $e_IsSelf_SessionId, $e_SessionName, $e_UserName, $e_SessionId, $e_StateName, $e_StateInt, $e_ClientName, $e_ClientIp, $e_Domain, $e_UBound
    Local Const $tagWTS_SESSION_INFO = 'dword SessionId;ptr WinStationName;uint State'
    Local $aResult = DllCall('wtsapi32.dll', 'int', 'WTSEnumerateSessionsW', 'ptr', 0, 'dword', 0, 'dword', 1, 'ptr*', 0, 'dword*', 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "") ; https://docs.microsoft.com/en-us/windows/desktop/api/wtsapi32/ne-wtsapi32-_wts_connectstate_class
    Local $aConnectionState = StringSplit("Active,Connected,ConnectQuery,Shadow,Disconnected,Idle,Listen,Reset,Down,Init", ",", 2)
    Local $tInfo, $Offset = 0, $c = 0, $aReturn[$aResult[5] + 1][$e_UBound] ; $e_UBound is the last enumerator, just to determine the size of the array
    $aReturn[0][$e_SessionId] = "ID"
    $aReturn[0][$e_SessionName] = "SessionName"
    $aReturn[0][$e_StateInt] = "StateInt"
    $aReturn[0][$e_StateName] = "State"
    $aReturn[0][$e_UserName] = "UserName"
    $aReturn[0][$e_ClientName] = "ClientName"
    $aReturn[0][$e_ClientIp] = "ClientIp"
    $aReturn[0][$e_Domain] = "Domain"
    For $i = 1 To $aResult[5]
        $tInfo = DllStructCreate($tagWTS_SESSION_INFO, $aResult[4] + $Offset)
        $Offset += DllStructGetSize($tInfo)
        $c += 1
        $aReturn[$c][$e_SessionId] = DllStructGetData($tInfo, 'SessionId')
        $aReturn[$c][$e_SessionName] = DllStructGetData(DllStructCreate('wchar[1024]', DllStructGetData($tInfo, 'WinStationName')), 1)
        $aReturn[$c][$e_StateInt] = DllStructGetData($tInfo, 'State')
        If UBound($aConnectionState) > $aReturn[$c][$e_StateInt] Then $aReturn[$c][$e_StateName] = $aConnectionState[$aReturn[$c][$e_StateInt]]
        $aReturn[$c][$e_UserName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 5) ; WTSUserName
        $aReturn[$c][$e_ClientName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 10) ; WTSClientName
        $aReturn[$c][$e_ClientIp] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 14) ; WTSClientAddress
        $aReturn[$c][$e_Domain] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 7) ; WTSDomainName
        $aReturn[0][$e_IsSelf_SessionId] = $c
        If $_Self_SessionId = $aReturn[$c][$e_SessionId] Then
            $aReturn[$c][$e_IsSelf_SessionId] = 1
        Else
            $aReturn[$c][$e_IsSelf_SessionId] = 0
        EndIf
    Next
    DllCall('wtsapi32.dll', 'none', 'WTSFreeMemory', 'ptr', $aResult[4])
    Return $aReturn
EndFunc   ;==>ListUserSessions

Func _WTSQuerySessionInformation($SessionId, $WTSInfoClass = 10, $iReturnAsIs = 0) ; mod. of https://www.autoitscript.com/forum/topic/134679-get-hostname-of-the-client-connected-to-the-terminalserver-session/
    Local $aResult = DllCall("Wtsapi32.dll", "int", "WTSQuerySessionInformation", "Ptr", 0, "int", $SessionId, "int", $WTSInfoClass, "ptr*", 0, "dword*", 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "")
    Local $ip = DllStructGetData(DllStructCreate("byte[" & $aResult[5] & "]", $aResult[4]), 1)
    DllCall("Wtsapi32.dll", "int", "WTSFreeMemory", "ptr", $aResult[4])
    If $iReturnAsIs Then Return $ip
    Switch $WTSInfoClass ; https://docs.microsoft.com/en-us/windows/desktop/api/wtsapi32/ns-wtsapi32-_wts_client_address
        Case 4 ; WTSSessionId
            Return Int('0x' & StringTrimRight(StringReverse($ip), 3))

        Case 14 ; WTSClientAddress
            If Not (Int(StringLeft($ip, 4)) = 2) Then ; IPv4
                $ip = ""
            Else
                $ip = Dec(StringMid($ip, 15, 2)) & '.' & Dec(StringMid($ip, 17, 2)) & '.' & Dec(StringMid($ip, 19, 2)) & '.' & Dec(StringMid($ip, 21, 2))
            EndIf

    EndSwitch
    Return StringReplace(BinaryToString($ip), Chr(0), "")
EndFunc   ;==>_GetWTSClientName

 

Edited by argumentum
better code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

  • 4 months later...

I just wanted to get the current users SessionID so I pulled just a little out of what you posted.

I also added the 29 to the function to verify that the session you specified is a Remote session or not.

 

The Microsoft link to figure out the WTSInfoClass values was broken but I found them and figured i'd post here in case someone else wants it.

 

;Options for the $SessionID
    Global Static $WTS_CURRENT_SESSION = -1

;Options for the $WTSInfoClass
    Global Static $WTSInitialProgram = 0
    Global Static $WTSApplicationName = 1
    Global Static $WTSWorkingDirectory = 2
    Global Static $WTSOEMId = 3
    Global Static $WTSSessionId = 4
    Global Static $WTSUserName = 5
    Global Static $WTSWinStationName = 6
    Global Static $WTSDomainName = 7
    Global Static $WTSConnectState = 8
    Global Static $WTSClientBuildNumber = 9
    Global Static $WTSClientName = 10
    Global Static $WTSClientDirectory = 11
    Global Static $WTSClientProductId = 12
    Global Static $WTSClientHardwareId = 13
    Global Static $WTSClientAddress = 14
    Global Static $WTSClientDisplay = 15
    Global Static $WTSClientProtocolType = 16
    Global Static $WTSIdleTime = 17
    Global Static $WTSLogonTime = 18
    Global Static $WTSIncomingBytes = 19
    Global Static $WTSOutgoingBytes = 20
    Global Static $WTSIncomingFrames = 21
    Global Static $WTSOutgoingFrames = 22
    Global Static $WTSClientInfo = 23
    Global Static $WTSSessionInfo = 24
    Global Static $WTSSessionInfoEx = 25
    Global Static $WTSConfigInfo = 26
    Global Static $WTSValidationInfo = 27
    Global Static $WTSSessionAddressV4 = 28
    Global Static $WTSIsRemoteSession = 29


$id = _WTSQuerySessionInformation($WTS_CURRENT_SESSION, $WTSSessionId) ;Get the current users SessionId
ConsoleWrite("My Session ID:  " & $id & @CRLF)

$Username = _WTSQuerySessionInformation($WTS_CURRENT_SESSION, $WTSUserName) ;Get the username for the specified session
ConsoleWrite("My Username:  " & $Username & @CRLF)

$Username = _WTSQuerySessionInformation($WTS_CURRENT_SESSION, $WTSIsRemoteSession) ;Can verify that the session is Remote
ConsoleWrite("IsRemote?  " & $Username & @CRLF)



Func _WTSQuerySessionInformation($SessionId = -1, $WTSInfoClass = 10, $iReturnAsIs = 0) ; mod. of https://www.autoitscript.com/forum/topic/134679-get-hostname-of-the-client-connected-to-the-terminalserver-session/
    Local $aResult = DllCall("Wtsapi32.dll", "int", "WTSQuerySessionInformation", "Ptr", 0, "int", $SessionId, "int", $WTSInfoClass, "ptr*", 0, "dword*", 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "")
    Local $ip = DllStructGetData(DllStructCreate("byte[" & $aResult[5] & "]", $aResult[4]), 1)
    DllCall("Wtsapi32.dll", "int", "WTSFreeMemory", "ptr", $aResult[4])
    If $iReturnAsIs Then Return $ip
    Switch $WTSInfoClass
        Case 4 ; We want the WTSSessionId
            Return Int('0x' & StringTrimRight(StringReverse($ip), 3))

        Case 29 ; 1 = this is a remote session, 0 means its a physical session  $WTSIsRemoteSession
            Return Int('0x' & StringTrimRight(StringReverse($ip), 3))

        Case 14 ; We want the WTSClientAddress
            If Not (Int(StringLeft($ip, 4)) = 2) Then ; IPv4
                $ip = ""
            Else
                $ip = Dec(StringMid($ip, 15, 2)) & '.' & Dec(StringMid($ip, 17, 2)) & '.' & Dec(StringMid($ip, 19, 2)) & '.' & Dec(StringMid($ip, 21, 2))
            EndIf

    EndSwitch
    Return StringReplace(BinaryToString($ip), Chr(0), "")
EndFunc   ;==>_GetWTSClientName

 

Link to comment
Share on other sites

  • 5 months later...

@argumentum

So I will be the first to admit I don't understand dll structure and converting back to readable data.  I have been toying with your listusersessions array trying to understand it and get it to pull the data I want.   But I need two additional columns of info.  WTSLogonTime & WTSIdleTime.  Here are the changes I have made to your base code but I don't think I am converting things correctly.  If you could help me understand what I am doing wrong and where I can find the different structures for each property.  I believe I want to create an array that list all the properties for all sessions.   I made no changes to the function  _WTSQuerySessionInformation

 

Func ListUserSessions() ; mod. of https://www.autoitscript.com/forum/topic/139774-dllcall-and-returned-pointers/?do=findComment&comment=980850
    Local $_Self_SessionId = _WTSQuerySessionInformation(-1, 4) ; -1 = current user ; 4 = WTSSessionId
    Local Enum $e_IsSelf_SessionId, $e_SessionName, $e_UserName, $e_SessionId, $e_StateName, $e_StateInt, $e_ClientName, $e_ClientIp, $e_Domain, $e_IdleTime, $e_LogonTime, $e_UBound
    Local Const $tagWTS_SESSION_INFO = 'dword SessionId;ptr WinStationName;uint State'
    Local $aResult = DllCall('wtsapi32.dll', 'int', 'WTSEnumerateSessionsW', 'ptr', 0, 'dword', 0, 'dword', 1, 'ptr*', 0, 'dword*', 0)
    If @error Or $aResult[0] = 0 Then Return SetError(1, 0, "") ; https://docs.microsoft.com/en-us/windows/desktop/api/wtsapi32/ne-wtsapi32-_wts_connectstate_class
    Local $aConnectionState = StringSplit("Active,Connected,ConnectQuery,Shadow,Disconnected,Idle,Listen,Reset,Down,Init", ",", 2)
    Local $tInfo, $Offset = 0, $c = 0, $aReturn[$aResult[5] + 1][$e_UBound] ; $e_UBound is the last enumerator, just to determine the size of the array
    $aReturn[0][$e_SessionId] = "ID"
    $aReturn[0][$e_SessionName] = "SessionName"
    $aReturn[0][$e_StateInt] = "StateInt"
    $aReturn[0][$e_StateName] = "State"
    $aReturn[0][$e_UserName] = "UserName"
    $aReturn[0][$e_ClientName] = "ClientName"
    $aReturn[0][$e_ClientIp] = "ClientIp"
    $aReturn[0][$e_Domain] = "Domain"
    $aReturn[0][$e_IdleTime] = "IdleTime"
    $aReturn[0][$e_LogonTime] = "LogonTime"
    For $i = 1 To $aResult[5]
        $tInfo = DllStructCreate($tagWTS_SESSION_INFO, $aResult[4] + $Offset)
        $Offset += DllStructGetSize($tInfo)
        $c += 1
        $aReturn[$c][$e_SessionId] = DllStructGetData($tInfo, 'SessionId')
        $aReturn[$c][$e_SessionName] = DllStructGetData(DllStructCreate('wchar[1024]', DllStructGetData($tInfo, 'WinStationName')), 1)
        $aReturn[$c][$e_StateInt] = DllStructGetData($tInfo, 'State')
        If UBound($aConnectionState) > $aReturn[$c][$e_StateInt] Then $aReturn[$c][$e_StateName] = $aConnectionState[$aReturn[$c][$e_StateInt]]
        $aReturn[$c][$e_UserName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 5) ; WTSUserName
        $aReturn[$c][$e_ClientName] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 10) ; WTSClientName
        $aReturn[$c][$e_ClientIp] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 14) ; WTSClientAddress
        $aReturn[$c][$e_Domain] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 7) ; WTSDomainName
        $aReturn[$c][$e_IdleTime] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 17) ; WTSIdleTime
        $aReturn[$c][$e_LogonTime] = _WTSQuerySessionInformation($aReturn[$c][$e_SessionId], 18) ; WTSLogonTime
        $aReturn[0][$e_IsSelf_SessionId] = $c
        If $_Self_SessionId = $aReturn[$c][$e_SessionId] Then
            $aReturn[$c][$e_IsSelf_SessionId] = 1
        Else
            $aReturn[$c][$e_IsSelf_SessionId] = 0
        EndIf
    Next
    DllCall('wtsapi32.dll', 'none', 'WTSFreeMemory', 'ptr', $aResult[4])
    Return $aReturn
EndFunc   ;==>ListUserSessions

 

Link to comment
Share on other sites

9 hours ago, Nhardel said:

Bump

Hey @Bump, to tell the truth, I did not code it. The links to the original code should be as comments in the code. I modified it to fit my needs after a long hours of trance like state.
I've got lots of unrelated work to do and can't afford the getting into the request right now, as I too suck at all these DLL stuff.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...