WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Terminal Server

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Get Terminal Session ID UDF

Keywords: Terminal server Session ID	

Question:

Is there a way to quickly determine if a user is logged in at the console of a server or using terminal services to access the server? I'm trying to avoid running a logon script on a Citrix server if the user is connected remotely.

Answer:

Yes, there is. However, the method varies somewhat based on whether you have WinNT v4.0 Terminal Server Edition, Win2K [Server or Advanced Server] in Terminal Server mode, or Win2K [Server or Advanced Server] running Citrix Metaframe v1.8a [or newer].

On Win2K, with or without Citrix, there is an environment variable named "SESSIONNAME" and it will have the value "Console" when you are logged in on the system console.

On WinNT v4.0 Terminal Server Edition there is a similar environment variable named "WINSTATIONNAME" that also provides the same information. Again, if you are on the server console then the value of the environment variable will also be "Console".

If you are logged in on the console of a NT/2K system that is *not* running the "Terminal Server" service [WinNT] or the "Terminal Services" service [Win2K], then neither of these environment variables will be defined in the user's environment.

Use the Environment() function in WinBatch to obtain the environment variable value for the appropriate environment variable. Obtaining the value of a non-existent environment variable will result in getting back an empty string as the return value of Environment(), so you can test for both environment variables very easily in a script.

Another thing that can be done is to attempt to get the terminal services session number. Use the following script snippet that defines a UDF to do this. If the UDF is called on a system that is not running any sort of terminal services then the return value is an empty string; otherwise, the return value is a session number. In all cases, session # zero "0" is the console. All other remote sessions that are initiated via the Terminal Services Client [RDP] or the Citrix Client [ICA] will have a non-zero session number that can be as high as the maximum # of concurrent users that are licensed on the server.

You can verify this by using the QUERY SESSION command at a console command prompt. The output of this command shows all of the terminal server sessions that exist, including the session # and the session name for each session. The session named "Console" always has session # zero "0".


Update: Use the wtsQuerySessionInfo function in the Terminial Services Extender.


; GetTSSessionID_UDF.wbt
; 32-bit UDF
;Debug(@ON)

#DefineFunction GetTSSessionID()

Title01 = 'GetTSSessionID()'
bFail = @FALSE
; Bail out and return an empty string [not on a TS-enabled system]
; if the required DLL does not exist.
if (FileLocate('WTSAPI32.DLL') == '') then return ''

;/*
; *  Specifies the current server
; */
;#define WTS_CURRENT_SERVER         ((HANDLE)NULL)
;#define WTS_CURRENT_SERVER_HANDLE  ((HANDLE)NULL)
;#define WTS_CURRENT_SERVER_NAME    (NULL)

WTS_CURRENT_SERVER = 0
WTS_CURRENT_SERVER_HANDLE = 0
WTS_CURRENT_SERVER_NAME = 0

;/*
; *  Specifies the current session (SessionId)
; */
;#define WTS_CURRENT_SESSION ((DWORD)-1)

WTS_CURRENT_SESSION = -1

;/*=====================================================================
;==   WTS_INFO_CLASS - WTSQuerySessionInformation
;==    (See additional typedefs for more info on structures)
;=====================================================================*/
;
;#define WTS_PROTOCOL_TYPE_CONSOLE         0    // Console
;#define WTS_PROTOCOL_TYPE_ICA             1    // ICA Protocol
;#define WTS_PROTOCOL_TYPE_RDP             2    // RDP Protocol
;
;typedef enum _WTS_INFO_CLASS {
;    WTSInitialProgram,          //  0
;    WTSApplicationName,         //  1
;    WTSWorkingDirectory,        //  2
;    WTSOEMId,                   //  3
;    WTSSessionId,               //  4
;    WTSUserName,                //  5
;    WTSWinStationName,          //  6
;    WTSDomainName,              //  7
;    WTSConnectState,            //  8
;    WTSClientBuildNumber,       //  9
;    WTSClientName,              // 10
;    WTSClientDirectory,         // 11
;    WTSClientProductId,         // 12
;    WTSClientHardwareId,        // 13
;    WTSClientAddress,           // 14
;    WTSClientDisplay,           // 15
;    WTSClientProtocolType,      // 16
;} WTS_INFO_CLASS;

WTSSessionId = 4

PtrBuf = BinaryAlloc(4)
BinaryPoke4(PtrBuf,0,0)

ResultBufSizeBuf = BinaryAlloc(4)
BinaryPoke4(ResultBufSizeBuf,0,0)

ErrorMode(@OFF)
Result = DllCall('WTSAPI32.DLL',long:'WTSQuerySessionInformationA',long:WTS_CURRENT_SERVER_HANDLE,long:WTS_CURRENT_SESSION,long:WTSSessionId,lpbinary:PtrBuf,lpbinary:ResultBufSizeBuf)
RC = LastError()
DllRC = DllLastError()
ErrorMode(@CANCEL)

if (RC != 0)
  TempMsg = StrCat('DllCall() failed!',@CRLF)
  TempMsg = StrCat(TempMsg,@CRLF,'Result = ',Result)
  TempMsg = StrCat(TempMsg,@CRLF,'RC = ',RC)
  TempMsg = StrCat(TempMsg,@CRLF,'DllRC = ',DllRC)
  Message(Title01,TempMsg)
  bFail = @TRUE
endif

if (bFail) then return ''

PtrBufAddr = BinaryPeek4(PtrBuf,0)
ResultBufSize = BinaryPeek4(ResultBufSizeBuf,0)

BinaryFree(PtrBuf)
BinaryFree(ResultBufSizeBuf)

PtrBuf = 0
ResultBufSizeBuf = 0

if (PtrBufAddr == 0)
;  Message(Title01,'Result buffer pointer is NULL!  Aborting...')
  bFail = @TRUE
endif

if (bFail) then return ''

if (ResultBufSize <= 0)
;  Message(Title01,'Result buffer size is zero!  Aborting...')
  bFail = @TRUE
endif

if (bFail) then return ''

ResultBuf = BinaryAlloc(ResultBufSize)

for i = 0 to (ResultBufSize - 1)
  TempByte = IntControl(32,PtrBufAddr + i,'BYTE',0,'')
  BinaryPoke(ResultBuf,i,TempByte)
next

BinaryEODSet(ResultBuf,ResultBufSize)

ErrorMode(@OFF)
Result = DllCall('WTSAPI32.DLL',void:'WTSFreeMemory',long:PtrBufAddr)
RC = LastError()
ErrorMode(@CANCEL)

SessionID = 0
SessionID = BinaryPeek4(ResultBuf,0)
BinaryFree(ResultBuf)
ResultBuf = 0
;MsgText = StrCat('Session ID = ',SessionID)
;Message(Title01,MsgText)

return SessionID

#EndFunction






Article ID:   W15339
File Created: 2011:11:09:09:23:36
Last Updated: 2011:11:09:09:23:36