Quantcast
Channel: Terminal Server – Remko Weijnen's Blog (Remko's Blog)

TSAdminEx

$
0
0

You will probably know Microsofts Tool to Manage Terminal Server, it’s called Terminal Services Manager (you will probably know it as TSAdmin). It can be used to view information about terminal servers including all sessions, users, and processes for each terminal server.

TSAdmin Screenshot

I’m currently working on a TSAdmin replacement (codename TSAdminEx). Purpose is to show how to use the Terminal Server API’s and as a little bonus we will add some extra functionality to TSAdminEx.


Well 1st step is to create the GUI and make it resemble TSAdmin, so we create a new Application and we place a Mainmenu, Toolbar (set Edgeborders to ebTop for the horizontal line) and Actionlist on it. 
Then we add a Treeview (set it’s Align property to alLeft) and a Splitter. Next add a bevel and a Panel, set Align to alClient and BevelOuter to bvLowered. Add a PageControl (align alClient) with 3 Tabsheets to the Panel and place a ListView on each Tabsheet.

TSAdminEx Screenshot

As you can see on the screenshot it’s already starting to look like TSAdmin after adding the Menus and Toolbar buttons.

So now we need to add some code but wait… now is your chance to add your functionality! Let me know by adding a comment what features you would like to see in TSAdminEx. Below what I’m currently thinking of:


Using WTSWaitSystemEvent

$
0
0

If you develop an application for Terminal Server you might want to react on session events. This means that your application is notified when a user logs on, logs off or becomes idle. This can be done with the WTSWaitSystemEvent function. Implementing it is rather simple and could look something like this:

procedure TJwWTSEventThread.Execute; 
begin 
  while not Terminated do 
  begin 
    if WTSWaitSystemEvent(ServerHandle, WTS_EVENT_ALL, FEventFlag) then 
    begin 
      Synchronize(DispatchEvent); 
    end; 
    Sleep(10); 
  end; 
end;

Notice that you would probably do this from a seperate thread otherwise you will block the main thread. To stop waiting for Events you send a special event:

// unblock the waiter 
WTSWaitSystemEvent(FServerHandle, WTS_EVENT_FLUSH, EventFlag);

Please note that there are at least 2 issues with this API, one with Windows 2000 and one with Windows Vista. On Windows 2000 events are reported twice for each actual event. Microsoft’s resolution?

The application should expect the event twice, and filter out the second occurrence.

Now how do we solve this? I would suggest introducing a small delay after an event trigger, this way you will probably not receive the duplicate event.

On Windows Vista there’s another issue: After you set the value of the EventMask parameter to WTS_EVENT_FLUSH in the WTSWaitSystemEvent function, no pending calls to the function return on a Windows Vista-based computer. Now what does this mean? It means that after sending WTS_EVENT_FLUSH the thread never responds! So there’s actually no nice way to end the thread, the only escape is a call to TerminateThread.

Microsoft does offer a hotfix, so my suggestion is a check on startup that will notify the user that he/she needs to install the hotfix. A version check can be done on winsta.dll, the version before the fix is 6.0.6000.16386. Hotfix version is 6.0.6000.20664. According to this article the fix will be included in Vista SP1.

References:

TSAdminEx Progress

$
0
0

I just wanted to show some of the progress that I made in development of TSAdminEx. I thought the best way would be to show some screenshots. Which reminds me I installed a nice Javascript to enlarge the thumbnails, click to see it…

Edit: A beta is ready!

This screenshot shows TSAdminEx after startup. In the Left Treeview you can see the This Computer, Favorites and All Listed Servers icon. On Startup all available domains are enumerated.
Here you see the Users tab. If you move the mouse over some columns you can get extra info in the hint. In this hint you get the actual shadow permissions of the highlighted session.
This is the Sessions tab where extra details of a session are shown. By default you can see sessions statistics such as Incomingbytes and Outgoingbytes, this makes it easy to identify sessions that have much traffic.Interesting detail is that the Remote Address column lists the real ip address that is connected to Terminal Server! Hovering the mouse also shows the port number.
Now the Process tab is my favorite! It lists far more details than TSAdmin and also some usefull columns that cannot be show with TSAdmin or any documented Terminal Server API!The Process Age columns shows how long the process is running. You can compare this with the CPU Time column to see how much CPU Time the process has allocated since startup.The Mem Usage shows the amount of physical RAM a process uses while the VM Size column shows the amount of Private Bytes (Virtual Memory) a process uses.
If you click on a domain in the Left Treeview, TSAdminEx will enumerate all Terminal Servers for that domain. You can continue using and even enumerate multiple domains, because enumeration is done from seperate threads!
If you select (highlight) a particular session the appropriate toolbar buttons are enabled or disabled automically indicating the actions that can be performed on the selected session.
And offcourse, an about dialog…

Hope you like it! Comments are open…

File not found error when scanning using Twain Redirection in Citrix XenApp

$
0
0

Twain LogoScanners attached to client machines can be used from within a Citrix XenApp session via a mechanism called Twain Redirection.

For this mechanism to work correctly the file twain_32.dll must be present in the Windows directory.

On Windows 2008 this dll should be copied from winsxs (side by side) to the windows directory as described in CTX123981.

On Windows 2003 the dll is already in the correct directory, however applications that are not Terminal Server Aware cannot find this dll because the Windows directory is redirected to the user profile. Citrix recommends copying twain_32.dll to each user’s profile directory but this will take up unnecessary space.

So what alternatives do we have?

Method 1: Adjust DllCharacteristics field in the executable
The afore mentioned link on MSDN lists a procedure to set the TSAWARE flag when compiling (linking) an executable. But when can also set this property on binary (.exe) files.

There are various tools that can do this such as Microsoft’s editbin that comes with Visual Studio. In this example I will use NTCore’s CFF Explorer.

Start CFF Explorer and load the target executable, select Optional Header in the Treeview and change DllCharacteristics:

Change DllCharacteristics filed in the Optional Header

    Check the option “Terminal Server Aware” and click OK:

Set Terminal Server Aware Flag

Now save and test the executable.

Method 2: Set Terminal Server Application Compatibility Flag:
This method has the advantage that it doesn’t need a modification to the executable. It does have to be set per server but you could easily do this with a deployment tool or script.

Open regedit and create a key with the executable name (without extension) under “HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications“.

In this key we need to set a Flags value for “Do not substitute user Windows directory” and “Windows 32-bit application”. The values are documented in Microsoft kb186499 as 0×00000400 and 0×00000008 which we need to “OR”.

So we create a DWORD named Flags and give the HEX value 408.

Or use the following reg file (don’t forget to change the executable name!):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\APROIMAGING]
"Flags"=dword:00000408

With both methods the twain_32.dll will correctly load from the Windows directory!

TSAdminEx

$
0
0

You will probably know Microsofts Tool to Manage Terminal Server, it’s called Terminal Services Manager (you will probably know it as TSAdmin). It can be used to view information about terminal servers including all sessions, users, and processes for each terminal server.

TSAdmin Screenshot

I’m currently working on a TSAdmin replacement (codename TSAdminEx). Purpose is to show how to use the Terminal Server API’s and as a little bonus we will add some extra functionality to TSAdminEx.


Well 1st step is to create the GUI and make it resemble TSAdmin, so we create a new Application and we place a Mainmenu, Toolbar (set Edgeborders to ebTop for the horizontal line) and Actionlist on it. 
Then we add a Treeview (set it’s Align property to alLeft) and a Splitter. Next add a bevel and a Panel, set Align to alClient and BevelOuter to bvLowered. Add a PageControl (align alClient) with 3 Tabsheets to the Panel and place a ListView on each Tabsheet.

TSAdminEx Screenshot

As you can see on the screenshot it’s already starting to look like TSAdmin after adding the Menus and Toolbar buttons.

So now we need to add some code but wait… now is your chance to add your functionality! Let me know by adding a comment what features you would like to see in TSAdminEx. Below what I’m currently thinking of:

Using WTSWaitSystemEvent

$
0
0

If you develop an application for Terminal Server you might want to react on session events. This means that your application is notified when a user logs on, logs off or becomes idle. This can be done with the WTSWaitSystemEvent function. Implementing it is rather simple and could look something like this:

procedure TJwWTSEventThread.Execute;
begin
  while not Terminated do
  begin
    if WTSWaitSystemEvent(ServerHandle, WTS_EVENT_ALL, FEventFlag) then
    begin
      Synchronize(DispatchEvent);
    end;
    Sleep(10);
  end;
end;

Notice that you would probably do this from a seperate thread otherwise you will block the main thread. To stop waiting for Events you send a special event:

// unblock the waiter
WTSWaitSystemEvent(FServerHandle, WTS_EVENT_FLUSH, EventFlag);

Please note that there are at least 2 issues with this API, one with Windows 2000 and one with Windows Vista. On Windows 2000 events are reported twice for each actual event. Microsoft’s resolution?

The application should expect the event twice, and filter out the second occurrence.

Now how do we solve this? I would suggest introducing a small delay after an event trigger, this way you will probably not receive the duplicate event.

On Windows Vista there’s another issue: After you set the value of the EventMask parameter to WTS_EVENT_FLUSH in the WTSWaitSystemEvent function, no pending calls to the function return on a Windows Vista-based computer. Now what does this mean? It means that after sending WTS_EVENT_FLUSH the thread never responds! So there’s actually no nice way to end the thread, the only escape is a call to TerminateThread.

Microsoft does offer a hotfix, so my suggestion is a check on startup that will notify the user that he/she needs to install the hotfix. A version check can be done on winsta.dll, the version before the fix is 6.0.6000.16386. Hotfix version is 6.0.6000.20664. According to this article the fix will be included in Vista SP1.

References:

TSAdminEx Progress

$
0
0

I just wanted to show some of the progress that I made in development of TSAdminEx. I thought the best way would be to show some screenshots. Which reminds me I installed a nice Javascript to enlarge the thumbnails, click to see it…

Edit: A beta is ready!

This screenshot shows TSAdminEx after startup. In the Left Treeview you can see the This Computer, Favorites and All Listed Servers icon. On Startup all available domains are enumerated.
Here you see the Users tab. If you move the mouse over some columns you can get extra info in the hint. In this hint you get the actual shadow permissions of the highlighted session.
This is the Sessions tab where extra details of a session are shown. By default you can see sessions statistics such as Incomingbytes and Outgoingbytes, this makes it easy to identify sessions that have much traffic.Interesting detail is that the Remote Address column lists the real ip address that is connected to Terminal Server! Hovering the mouse also shows the port number.
Now the Process tab is my favorite! It lists far more details than TSAdmin and also some usefull columns that cannot be show with TSAdmin or any documented Terminal Server API!The Process Age columns shows how long the process is running. You can compare this with the CPU Time column to see how much CPU Time the process has allocated since startup.The Mem Usage shows the amount of physical RAM a process uses while the VM Size column shows the amount of Private Bytes (Virtual Memory) a process uses.
If you click on a domain in the Left Treeview, TSAdminEx will enumerate all Terminal Servers for that domain. You can continue using and even enumerate multiple domains, because enumeration is done from seperate threads!
If you select (highlight) a particular session the appropriate toolbar buttons are enabled or disabled automically indicating the actions that can be performed on the selected session.
And offcourse, an about dialog…

Hope you like it! Comments are open…

File not found error when scanning using Twain Redirection in Citrix XenApp

$
0
0

Twain LogoScanners attached to client machines can be used from within a Citrix XenApp session via a mechanism called Twain Redirection.

For this mechanism to work correctly the file twain_32.dll must be present in the Windows directory.

On Windows 2008 this dll should be copied from winsxs (side by side) to the windows directory as described in CTX123981.

On Windows 2003 the dll is already in the correct directory, however applications that are not Terminal Server Aware cannot find this dll because the Windows directory is redirected to the user profile. Citrix recommends copying twain_32.dll to each user’s profile directory but this will take up unnecessary space.

So what alternatives do we have?

Method 1: Adjust DllCharacteristics field in the executable
The afore mentioned link on MSDN lists a procedure to set the TSAWARE flag when compiling (linking) an executable. But when can also set this property on binary (.exe) files.

There are various tools that can do this such as Microsoft’s editbin that comes with Visual Studio. In this example I will use NTCore’s CFF Explorer.

Start CFF Explorer and load the target executable, select Optional Header in the Treeview and change DllCharacteristics:

Change DllCharacteristics filed in the Optional Header

    Check the option “Terminal Server Aware” and click OK:

Set Terminal Server Aware Flag

Now save and test the executable.

Method 2: Set Terminal Server Application Compatibility Flag:
This method has the advantage that it doesn’t need a modification to the executable. It does have to be set per server but you could easily do this with a deployment tool or script.

Open regedit and create a key with the executable name (without extension) under “HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications“.

In this key we need to set a Flags value for “Do not substitute user Windows directory” and “Windows 32-bit application”. The values are documented in Microsoft kb186499 as 0x00000400 and 0x00000008 which we need to “OR”.

So we create a DWORD named Flags and give the HEX value 408.

Or use the following reg file (don’t forget to change the executable name!):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Compatibility\Applications\APROIMAGING]
"Flags"=dword:00000408

With both methods the twain_32.dll will correctly load from the Windows directory!