Terminal Server API Programming in C# (Part 2)
This is Part II of my Terminal Server API Programming. You can read Part I here.
As to my Terminal Services code I have found that an enumeration thru the sessions was going to give me more overhead then I wanted. Therefore I found you can use the WTSQuerySessionInformation once you have the session you want. To get the session that I want I find the processId that my current application is running and from that I use a ProcessIdToSessionId from the kernel32 assembly.
Add one more p/invoke:
[DllImport("kernel32.dll")]
internal static extern bool ProcessIdToSessionId(uint dwProcessId, out uint pSessionId);
Download Code Here:
Let’s review the code.
First off I created a NativeMethods.cs class that houses all my Imported Dll’s I have separated this class into a safe and UnsafeNativeMethods. Any method that uses the UnmanagedType Gets placed in the UnsafeNativeMethods, which at the top of the class I use the [SuppressUnmanagedCodeSecurity] attribute.
In the SessionInfoHelper.cs Class, everything in this class supports the call to SessionInfoBag GetClientInfo(). My company wanted to make one call to this and return all the information to be used. SessionInfoBag is my custom object that houses the structure of data that I need. Currently you will find:
SessionInfoBag:
· SessionId – The final sessionId that the current client is using.
· Type – Is this a RDP or ISA (Citrix)
· User – The connected username used
· Machine – The machine of the connected session
· ProcessId - Current application ProcessId
· IsRemoteLogin – Is this connection a remote login (RDP or Citrix) or not.
I also have a ProcessInfoBag k which contains the ProcessId and the ProcessSessionId
In the Session Helper class I also wrapped the OpenServer and CloseServer Invokes just to add another level of abstraction.
Lets walk thru the control of the class.
1) Call GetClientInfo()
a. Create Structures
b. Get Process Information
c. ProcessInfoBag GetCurrentProcessInfo()//Populates ProcessInfoBag
d. Check for a Remote Connection and set the bool if it is
i. If this is a remote session then let’s call “GetSession” and pass in the info (we have found the correct sessionId by this point)
ii. Else let’s populate the SessionInfoBag object with local variables.
e. Return Client Info
In the GetSession ():
1) Open Server
2) Since we now know the exact session we want on the server we use a point target search. This is done with the UnsafeNativeMethods.WTSQuerySessionInformation
a. When done with that we populate the SessionInfoBag with this returned data.
b. Close the Server
c. FreeUpMemory
It’s a fairly straight forward solution utilizing the WTS Services for both Citrix and RDP in one class.