Like me, when I created this application, you might be wondering how you can grab information about a terminal services session programatically might be because you have an application that checks the Users IP to do some additional configuration on the application surface / environment or you might have an application that you need to render differently depending on the clients' resolution on the terminal services.
Well without a Terminal Services Session, getting this information will be really easy like getting an IP from the application as an example:
System.Net.IPAddress[] YourIPs =
System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName());
for (int i = 0; i < YourIPs.Length; i++)
{
Console.WriteLine("IP Address {0}: {1} ", i, YourIPs[i].ToString());
}
or getting a resolution:
using System.Drawing;
using System.Windows.Forms;
Console.WriteLine(SystemInformation.PrimaryMonitorSize.ToString());
As you can see, it's really easy as there are .NET References for it but doing it in a Terminal Service Session will give you a different story as you will get the server environment results. Also you have to consider that there are no .NET references for Terminal Services Session and we have to import Wtsapi32.dll to achieve the results you want.
So what is Wtsapi32.dll? It is a Remote Desktop Services API that provides additional functionality which is related to a Remote Desktop Environment. To get started, I will give you a sample down below on how would we import this DLL to our application as well as how to consume the methods it exposes.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
class Program
{
#region Constants
public const int WTS_CURRENT_SESSION = -1;
#endregion
#region Dll Imports
[DllImport("wtsapi32.dll")]
static extern int WTSEnumerateSessions(
IntPtr pServer,
[MarshalAs(UnmanagedType.U4)] int iReserved,
[MarshalAs(UnmanagedType.U4)] int iVersion,
ref IntPtr pSessionInfo,
[MarshalAs(UnmanagedType.U4)] ref int iCount);
[DllImport("Wtsapi32.dll")]
public static extern bool WTSQuerySessionInformation(
System.IntPtr pServer,
int iSessionID,
WTS_INFO_CLASS oInfoClass,
out System.IntPtr pBuffer,
out uint iBytesReturned);
[DllImport("wtsapi32.dll")]
static extern void WTSFreeMemory(
IntPtr pMemory);
#endregion
#region Structures
[StructLayout(LayoutKind.Sequential)]
private struct WTS_CLIENT_ADDRESS
{
public int iAddressFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] bAddress;
}
[StructLayout(LayoutKind.Sequential)]
private struct WTS_SESSION_INFO
{
public int iSessionID;
[MarshalAs(UnmanagedType.LPStr)]
public string sWinsWorkstationName;
public WTS_CONNECTSTATE_CLASS oState;
}
[StructLayout(LayoutKind.Sequential)]
private struct WTS_CLIENT_DISPLAY
{
public int iHorizontalResolution;
public int iVerticalResolution;
public int iColorDepth;
}
#endregion
#region Enumurations
public enum WTS_CONNECTSTATE_CLASS
{
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
public enum WTS_INFO_CLASS
{
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,
WTSConfigInfo,
WTSValidationInfo,
WTSSessionAddressV4,
WTSIsRemoteSession
}
#endregion
static void Main(string[] args)
{
IntPtr pServer = IntPtr.Zero;
string sUserName = string.Empty;
string sDomain = string.Empty;
string sClientApplicationDirectory = string.Empty;
string sIPAddress = string.Empty;
WTS_CLIENT_ADDRESS oClientAddres = new WTS_CLIENT_ADDRESS();
WTS_CLIENT_DISPLAY oClientDisplay = new WTS_CLIENT_DISPLAY();
IntPtr pSessionInfo = IntPtr.Zero;
int iCount = 0;
int iReturnValue = WTSEnumerateSessions
(pServer, 0, 1, ref pSessionInfo, ref iCount);
int iDataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
int iCurrent = (int)pSessionInfo;
if (iReturnValue != 0)
{
for (int i = 0; i < iCount; i++)
{
WTS_SESSION_INFO oSessionInfo =
(WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)iCurrent,
typeof(WTS_SESSION_INFO));
iCurrent += iDataSize;
uint iReturned = 0;
IntPtr pAddress = IntPtr.Zero;
if (WTSQuerySessionInformation(pServer,
oSessionInfo.iSessionID, WTS_INFO_CLASS.WTSClientAddress,
out pAddress, out iReturned) == true)
{
oClientAddres = (WTS_CLIENT_ADDRESS)Marshal.PtrToStructure
(pAddress, oClientAddres.GetType());
sIPAddress = oClientAddres.bAddress[2] + "." +
oClientAddres.bAddress[3] + "." + oClientAddres.bAddress[4]
+ "." + oClientAddres.bAddress[5];
}
if (WTSQuerySessionInformation(pServer,
oSessionInfo.iSessionID, WTS_INFO_CLASS.WTSUserName,
out pAddress, out iReturned) == true)
{
sUserName = Marshal.PtrToStringAnsi(pAddress);
}
if (WTSQuerySessionInformation(pServer,
oSessionInfo.iSessionID, WTS_INFO_CLASS.WTSDomainName,
out pAddress, out iReturned) == true)
{
sDomain = Marshal.PtrToStringAnsi(pAddress);
}
if (WTSQuerySessionInformation(pServer,
oSessionInfo.iSessionID, WTS_INFO_CLASS.WTSClientDisplay,
out pAddress, out iReturned) == true)
{
oClientDisplay = (WTS_CLIENT_DISPLAY)Marshal.PtrToStructure
(pAddress, oClientDisplay.GetType());
}
if (WTSQuerySessionInformation(pServer, oSessionInfo.iSessionID,
WTS_INFO_CLASS.WTSClientDirectory, out pAddress, out iReturned) == true)
{
sClientApplicationDirectory = Marshal.PtrToStringAnsi(pAddress);
}
Console.WriteLine("Session ID : " + oSessionInfo.iSessionID);
Console.WriteLine("Session State : " + oSessionInfo.oState);
Console.WriteLine("Workstation Name : " +
oSessionInfo.sWinsWorkstationName);
Console.WriteLine("IP Address : " + sIPAddress);
Console.WriteLine("User Name : " + sDomain + @"\" + sUserName);
Console.WriteLine("Client Display Resolution: " +
oClientDisplay.iHorizontalResolution + " x " +
oClientDisplay.iVerticalResolution);
Console.WriteLine("Client Display Colour Depth: " +
oClientDisplay.iColorDepth);
Console.WriteLine("Client Application Directory: " +
sClientApplicationDirectory);
Console.WriteLine("-----------------------");
}
WTSFreeMemory(pSessionInfo);
}
}
}
And here is the result: