Sessão WTS – VB.NET

Neste post irei mostrar um código em VB.NET de uma classe chamada clsWTS. Esta classe retorna algumas informações básicas de uma conexão remota conectada em uma estação.

Esta classe utiliza duas API’s (User32.dll e WtsApi32.dll) do Windows para obter as informações a seguir:

• IsRemoteSession: verifica se é uma sessão remota;
• ClientLoginName: login do client conectado;
• ClientComputerName: nome da máquina na rede do client conectado;
• ClientDomainName: domínio do client conectado;
• ClientIPAddress: endereço IP do client que está realizando a sessão remota;
• SessionName: nome da sessão do client conectado.

Código da classe:

Imports System.Runtime.InteropServices

Public Class clsCWTS

#Region "APIs"

    Private Declare Function WTSQuerySessionInformationA Lib "wtsapi32.dll" (ByVal hServer As Integer, ByVal SessionID As Integer, ByVal WTSInfoClass As WTS_INFO_CLASS, ByRef ppBuffer As Integer, ByRef pBytesReturned As Integer) As Integer
    Private Declare Sub WTSFreeMemory Lib "wtsapi32.dll" (ByVal pMemory As Integer)
    Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Integer) As Integer
    Private Declare Function lstrlenA Lib "kernel32.dll" (ByVal lpString As Integer) As Integer
    Private Declare Function lstrcpyA Lib "kernel32.dll" (ByVal lpString1 As String, ByVal lpString2 As Integer) As Integer
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal pDst As Byte, ByVal pSrc As Integer, ByVal ByteLen As Integer)
    Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Integer
    Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Integer, ByVal lpProcName As String) As Integer
    Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Integer) As Integer
    Private Declare Function WTSQuerySessionInformation2 Lib "WtsApi32.dll" Alias "WTSQuerySessionInformationW" (ByVal hServer As Int32, ByVal SessionId As Int32, ByVal WTSInfoClass As Int32, ByRef ppBuffer As IntPtr, ByRef pCount As Int32) As Boolean

    <DllImport("wtsapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Private Shared Function WTSOpenServer(ByVal pServerName As String) As IntPtr
    End Function

#End Region

#Region "Constantes"
    Private Const SM_REMOTESESSION As Integer = &H1000
    Private Const WTS_CURRENT_SERVER_HANDLE As Integer = 0&
    Private Const WTS_CURRENT_SERVER = 0&
    Private Const WTS_CURRENT_SESSION As Integer = -1

    Private Const AF_INET = 2
    Private Const AF_IPX = 6
    Private Const AF_NETBIOS = 17
    Private Const AF_UNSPEC = 0
#End Region

#Region "Enums e Structures"
    Private Enum WTS_INFO_CLASS
        WTSInitialProgram
        WTSApplicationName
        WTSWorkingDirectory
        WTSOEMId
        WTSSessionId
        WTSUserName
        WTSWinStationName
        WTSDomainName
        WTSconnectState
        WTSClientBuilderNumber
        WTSClientName
        WTSClientDirectory
        WTSClientProductId
        WTSClientHardwareId
        WTSClientAddress
        WTSClientDisplay
        WTSClientProtocolType
    End Enum

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure _WTS_CLIENT_ADDRESS
        Public AddressFamily As Integer
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> _
        Public Address() As Byte
    End Structure
#End Region

#Region "Variáveis"
    Private m_bolIsRemoteSession As Boolean
    Private m_strWTSClientName As String
    Private m_strWTSUserName As String
    Private m_strWTSDomainName As String
    Private m_strWTSWinStationName As String
    Private m_strClientIPAddress As String
#End Region

#Region "Inicialização da classe"
    Public Sub New()
        QueryWTSSession()
    End Sub
#End Region

#Region "Properties (ReadOnly)"
    Public ReadOnly Property IsRemoteSession() As Boolean
        Get
            IsRemoteSession = m_bolIsRemoteSession
        End Get
    End Property

    Public ReadOnly Property ClientLoginName() As String
        Get
            ClientLoginName = m_strWTSUserName
        End Get
    End Property

    Public ReadOnly Property ClientComputerName() As String
        Get
            ClientComputerName = m_strWTSClientName
        End Get
    End Property

    Public ReadOnly Property ClientDomainName() As String
        Get
            ClientDomainName = m_strWTSDomainName
        End Get
    End Property

    Public ReadOnly Property ClientIPAddress() As String
        Get
            ClientIPAddress = m_strClientIPAddress
        End Get
    End Property

    Public ReadOnly Property SessionName() As String
        Get
            SessionName = m_strWTSWinStationName
        End Get
    End Property
#End Region

#Region "Funções relacionadas à classe clsCWTS"
    Private Sub QueryWTSSession()

        Dim btLinhaErro As Single = 0

        Try
            Dim lpBuffer As Integer = 0
            Dim lngBytesReturned As Integer = 0

            btLinhaErro = 1
            m_bolIsRemoteSession = (GetSystemMetrics(SM_REMOTESESSION) <> 0)
            If Not m_bolIsRemoteSession Then
                Exit Sub
            End If

            btLinhaErro = 2
            If Not IsProcedureAvailable("wtsapi32.dll", "WTSQuerySessionInformationA") Then
                Exit Sub
            End If

            btLinhaErro = 3
            If WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS.WTSClientName, lpBuffer, lngBytesReturned) Then
                m_strWTSClientName = LPSTRtoBSTR(lpBuffer)
                WTSFreeMemory(lpBuffer)
            End If

            btLinhaErro = 4
            If WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS.WTSUserName, lpBuffer, lngBytesReturned) Then
                m_strWTSUserName = LPSTRtoBSTR(lpBuffer)
                WTSFreeMemory(lpBuffer)
            End If

            btLinhaErro = 5
            If WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS.WTSDomainName, lpBuffer, lngBytesReturned) Then
                m_strWTSDomainName = LPSTRtoBSTR(lpBuffer)
                WTSFreeMemory(lpBuffer)
            End If

            btLinhaErro = 6
            If WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS.WTSWinStationName, lpBuffer, lngBytesReturned) Then
                m_strWTSWinStationName = LPSTRtoBSTR(lpBuffer)
                WTSFreeMemory(lpBuffer)
            End If

            btLinhaErro = 7
            Dim iptAddress As IntPtr = IntPtr.Zero
            Dim ptrOpenedServer As IntPtr = WTSOpenServer(String.Empty)
            Dim intReturned As Integer = 0

            If WTSQuerySessionInformation2(ptrOpenedServer, 0, WTS_INFO_CLASS.WTSClientAddress, iptAddress, intReturned) = True Then
                Dim wtsAddress As New _WTS_CLIENT_ADDRESS()
                wtsAddress = CType(Marshal.PtrToStructure(iptAddress, wtsAddress.GetType()), _WTS_CLIENT_ADDRESS)
                m_strClientIPAddress = String.Concat(wtsAddress.Address(2) & "." & wtsAddress.Address(3) & "." & _
                                                      wtsAddress.Address(4) & "." & wtsAddress.Address(5))
            End If

        Catch ex As Exception
            Dim strMsg As String = ex.Message
            Throw New Exception("Error in QueryWTSession. Row: " & btLinhaErro & " Msg: " & strMsg)
        End Try

    End Sub

    Private Function LPSTRtoBSTR(ByVal lpBuffer As Integer) As String
        Dim lngChars As Integer = 0
        Dim strChars As String = String.Empty

        lngChars = lstrlenA(lpBuffer)

        If lngChars > 0 Then
            strChars = New String(Chr(0), lngChars)
            lstrcpyA(strChars, lpBuffer)
        End If

        LPSTRtoBSTR = strChars
    End Function

    Private Function IsProcedureAvailable(ByVal ModuleName As String, ByVal ProcName As String) As Boolean
        Dim hMod As Integer
        Dim pAddr As Integer

        hMod = LoadLibrary(ModuleName)

        If hMod Then
            pAddr = GetProcAddress(hMod, ProcName)
            FreeLibrary(hMod)
        End If

        IsProcedureAvailable = (pAddr <> 0)
    End Function
#End Region

End Class

Um exemplo simples de como obter as informações desta classe:

        Try
            Dim WTS As New clsCWTS
            'Só exibe as informações caso a conexão seja remota (Windows Terminal Services)
            If WTS.IsRemoteSession Then
                MsgBox("Client Computer Name: " & WTS.ClientComputerName & vbCrLf & _
                       "Client Domain Name:" & WTS.ClientDomainName & vbCrLf & _
                       "Client IP Address: " & WTS.ClientIPAddress & vbCrLf & _
                       "Client Login Name: " & WTS.ClientLoginName & vbCrLf & _
                       "Session Name: " & WTS.SessionName)
            Else
                MsgBox("A sessão não é uma sessão remota!")
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

Neste link você pode baixar o código-fonte exemplo que criei. O código-fonte foi compilado (x86) com o Visual Studio 2008.

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s