WTStek.com Windows Terminal Server, Virtualization, Application Delivery, Windows Software Development, Market Analysis, Training Classes and more...
Navigation

The Book

  Table of Content
  Preface
  About This Book

Part I A Beginner's Guide to Terminal Services

1 Terminal Services Overview
2 System Installation
3 Licensing
4 System Configuration
5 User Access and Client Software
6 Application Installation
7 System Administration and Operation
8 Server Sizing and Scalability

Part II – An Expert's Guide to Terminal Services

9 Terminal Server Internals
10 Network Planning and High Availability
11 User Environment
12 Access and Security
13 Printing
14 Registry
15 Scripting
16 Web Technologies

Part III – Terminal Services Complementary Concepts

17 Third Party Extension Products
18 Desktop and Application Virtualization
19 Deployment Automation
20 Resource and Security Management
21 Testing and Quality Assurance
22 Optimization and Performance Tuning
23 Project Methodology
24 Terminal Services API

My Profile

... About this Web Site
... Benny's Biography
... Presentations 2008, 2007, 2006, 2005, 2004 and earlier

 


Awards

 

Microsoft MVP

 

Provision Networks / Quest VIP

 

Microsoft Windows Server 2008 Terminal Services

6. Application Installation

Posted by Benny Tritsch on August 1, 2008

[Application Installation] [Multi-User Requirements] [Install Procedures] [Support Tools] [Samples]

Back Next

6.1. Application Requirements in Multi-User Environments

Read in this lesson...

  1. Application Categories
  2. Conventional Windows Application Requirements

  3. Framework Applications

 

Basically, the Microsoft programming principles for Windows applications should ensure proper functioning of programs that are used in multiple instances by multiple users. In the past, however, many application developers did not strictly follow these principles, making subsequent system improvements necessary to run their applications within a terminal server environment. The adjustments involve registry handling as well as directory structures and file access permissions.

Application Categories

In a pure terminal server-based environment, Windows applications run on the server platforms only. The clients do not execute any type of local application logic. Client devices display only the user interface and accept input. Of course, applications on the server do need to support this scenario.

NOTE: A conventional Windows application is an application based on unmanaged code. Therefore, statements made in the context of conventional Windows applications may not apply to Windows applications that are built on the .NET Framework (Windows Forms). Such Windows Forms are based on managed code. They will be addressed separately.

When evaluating applications, you need to look at several categories that are based on different fundamental technologies or require different conditions.

  1. Conventional 32-bit or 64-bit Windows applications that access the public Application Programming Interface (Windows API) of the operating system.
  2. Applications that are based on the .NET Windows Forms concept and generally behave like conventional Windows applications.
  3. Web Applications that are based on the Microsoft ASP.NET Web Forms concept or any other Web technology. Web servers such as the Microsoft Internet Information Server control their processing logic.

Let us now look in detail at conventional Windows applications and .NET Windows Forms applications. Web applications and their integration into terminal server environments will be covered in a separate chapter.

Conventional Windows Application Requirements

A conventional Windows application that meets some basic requirements can be used freely in Windows Server 2008 multiple-user environments. It is of central importance that installed applications can be used simultaneously by more than one interactive user. This means that no application should shows instances limitations and issues regarding global mutual exclusions. In order to be compatible to multi-user environments an application instance must never consume all system resources in terms of CPU, input/output and memory. The application installation must be robust and self-repairing, minimizing any conflicts between shared components (such as DLLs). This allows different applications to peacefully coexist on one platform.

Naturally, the application should be able to run in a strictly controlled network environment and allow administrators to set the security and user interface parameters. Finally, an application must be able to provide a clear migration path for converting from an earlier version of Windows to Windows Server 2008.

Installation, Configuration and Security Settings

A properly designed Windows application provides a robust unattended and silent installation routine including initial configuration options. The installation is directed to Program Files by default, ideally using the appropriate environment variable ProgramFiles. The installation process prevents to overwrite non-proprietary files with older versions. Additionally, it supports “Add or Remove Programs” and “All Users” installation properly. During installation there should be no replacement of files that are protected by Windows File Protection and no inappropriate reboots. An ideal installation routine allows administrators to pre-configure security and user interface parameters according to company rules.

Due to the potential challenges described here, some applications' installation routines need to be adapted for terminal servers to establish a working system environment without having to change the applications and installation programs themselves.

If these basic installation requirements are met, the application is easily distributed in a networked environment and ensures easy administration within organized structures. But there are more desired features when an application needs to be well suited for terminal servers. An ideal application can save user-specific settings in one central profile and thus allows you to manage roaming users. It supports multiple users per computer and recreates application settings if a computer needs to be physically exchanged. General system settings and user-specific data are strictly separated. Optimally, this type of application also supports several different clients with their own specific user interface characteristics in terms of screen sizes, color resolutions or supported fonts.

Sometimes the enhanced security requirements of terminal servers generate additional challenges. Security issues can introduce unexpected problems with installation routines and runtime behavior. This is why applications must execute properly with standard or limited user permissions when installed on a terminal server; local administrator privileges are not required. Applications should not require read/write access to local machine registry and system file areas. For maximum terminal server compatibility, application defaults do not bypass standard system security and deals gracefully with access-denied scenarios.

Application Components and User Data

All components of an application, which are executed on a terminal server, need to be programmed in a way that several users can work with them at the same time. Consequently, the following terminal server-specific conditions for user data and files need to be met:

  • Separate memory areas: Several application instances executed by different users should not access shared memory areas containing user-specific data to prevent unwanted data exchange between two user sessions.
  • File access lockout: When a user accesses a file belonging to an application, access to the same file should not be locked for other users. Otherwise, only one application instance can be executed.
  • File access permissions: Non-administrative users should probably not have access to system files or have the same permissions as administrators. It is recommended to avoid setups that would, for instance, prevent users who did not install an application from starting it.
  • File saving location: User-specific data and configuration files must be saved in separate, user-specific locations to avoid collisions and to manage access permissions. An application should be able to save all user-generated data within files in a user-specific folder. The application should be configured to point to the user's home directory as the default archive directory. This data requires the application to handle certain conventions, such as file access over the network or home directories with long names. User-specific application data is essential for terminal servers because terminal server users usually save user data on file servers on the network, not locally.
  • System file access: An application must not write into the system folder at runtime.
  • User-specific temporary files: Applications often create temporary data in temporary system folders. However, if several users are working on the system simultaneously, the temporary data must be strictly separated. Otherwise data might get mixed up and possibly result in unauthorized data access. If the user-specific temporary directories are used properly, such problems will not occur.

At first glance, this does not seem complicated. However, in reality, older applications usually do not expect to be used in a multiple-user environment. They therefore make certain assumptions about their run-time environment and behave accordingly. If this type of application is further developed, legacy design decisions often survive, even though they are not in keeping with the terminal server requirements previously discussed.

Frequently, applications running on terminal servers use dynamic link libraries (DLLs). DLLs are software components and they can be used by several applications. There are no general mechanisms to manage different DLL versions. For this reason, an application that accesses DLLs is not guaranteed to work properly.

Under Windows 2000, side-by-side DLL (SxS DLL) support was introduced and is still available under Windows Server 2008. It allows parallel use of several DLL versions on one system. However, SxS DLL did nothing to make DLL management easier, which is why the term DLL hell evolved with respect to the susceptibility to failure of complex Windows environments. This, of course, is not a terminal server-only problem; the multiple-user environment just highlights it more.

The challenges with DLLs can be solved by managing components more strictly on application level. In reality, this means to follow some simple rules when developing and maintaining DLLs for applications:

  • Never replace system DLLs.
  • Build DLL version control into the application.
  • Preserve backward compatibility with older DLLs.

Registry and Ini Files

The registry manages system and user configurations. Unfortunately, not all programs handle the differences between system und user settings as carefully as they should. This might be acceptable for systems that are used by a single individual. For terminal servers, this could mean a mixing of information from different users.

From a historical point of view, ini files were used before the registry was introduced. They were used to save and reload system and configuration data. All this happened at a central system location and therefore did not support differentiation between users. Older applications that use .ini files are therefore a special challenge when working with terminal servers.

Programming Terminal Server-Compatible Applications

Through corresponding API functions, conventional applications are able to access system functions and data structures specific to terminal servers. This allows the development of applications, which are aware of being run on terminal servers. In this way, developers can predefine a certain program behavior that applies only to terminal servers. A great example is an application running on Windows Vista that unambiguously identifies its user through a computer property, such as the IP address.

On a terminal server, however, this property is not unique to each user and thus might prevent simultaneous use of the application by several users. A solution can be to design the application in such a way it recognizes that it is running on a terminal server and switches to a mode that selects the user name as the unique differentiating feature.

It is, of course, preferable to avoid such dependencies right from the start, when the application is being developed. Additionally, to make applications as compatible as possible to terminal servers, specific functions for handling printers, registry, and user environment should be strictly based on standard Windows API calls. No hard coded paths like C:\Windows, C:\Program files or C:\Temp should be used in application code. Instead, using environment variables is highly recommended.

Framework Applications

In the summer of 2000, Microsoft announced the development of the .NET Framework, which allows new types of applications for the Windows platform. The .NET Framework has been on the market since the beginning of 2002 and supports three different types of applications:

  • ASP.NET Web Forms: This type of application runs on Web servers (such as Internet Information Services) and generates output in HTML format (as Web forms). To display the GUI and interact with the application, the client requires a web browser. The application logic is encoded with a technology called ASP.NET. Web forms do not usually have a role on terminal servers, but they can have an indirect impact if they are used as to implement an application access portal.
  • XML Web Services: These applications also run on web servers, but they interact with programs instead of users. Web services thus represent a technology for developing modular software components that can be distributed on the network by means of a formal description and standard protocols. Web services are normally based on eXtensible Markup Language (XML) for data and document formats, Web Services Description Language (WSDL) to describe messages and services, and the Simple Object Access Protocol (SOAP) for communication among the software modules. Web services do not usually run on terminal servers.
  • .NET Windows Forms: Windows Forms are the modern descendants of conventional Windows programs. They normally run in one window on the Windows desktop and can therefore be installed on terminal servers. If so programmed, Windows Forms can access Web services via the default interfaces and use their functions and methods. .NET Framework offers class libraries that can be used to develop Windows Forms applications.

Windows Server 2008 comes with the .NET Framework 3.0, which first needs to be activated before it can be used. It is, however, possible to install the new .NET Framework version 3.5.

.NET Framework Concepts

The three Framework application types have one thing in common: they do not communicate directly with the public API of the operating system. They need a runtime environment as an intermediate layer, the common language runtime (CLR), which is able to process any application code written in Microsoft Intermediate Language Code (MSIL code). This platform-independent code is also known as managed code because it is strictly controlled by the runtime environment instance. The .NET common language runtime was developed primarily for security, platform independence and not to be limited to any specific programming language.

For an application developed in a high-level, .NET-compliant programming language, such as C# or Microsoft Visual Basic .NET, a compiler transforms the source code into object code, now called Microsoft Intermediate Language code. The result in MSIL is then bundled into executable and transportable packages called assemblies. Because the CLR controls the code in MSIL, it is easier to control security than in conventional applications. In rough terms, MSIL is like the assembler code of a Framework application and as such can be modified directly. However, a developer usually uses one of the .NET programming languages, not MSIL.

A .NET assembly is a self-contained unit that contains all the metadata, resources, and data it needs. A complete Framework application consists of at least one assembly, which you can install on a platform simply by copying it. Conceptually, no registration is required, but it is recommendable to perform any installation processes within a proper setup routine. Additional functions can be encapsulated in further assemblies. These assemblies must be located in the same folder or in a sub-folder. You can also use an XML file to determine where the runtime environment should look for additional assemblies.

Assemblies used by more than one application are an exception. They are saved in a special folder, the %SystemRoot% \Assembly folder, also called the Global Assembly Cache (GAC). All assemblies in the GAC need to have a name, a version number, a public key, and a signature for unambiguous identification. All these elements comprise the strong name. The combination of assemblies, predefined folders, and strong names wards off the DLL hell of conventional 32-bit applications.

What happens if you want to run a Framework application that is an assembly in Microsoft Intermediate Language Code? In the case of .NET Windows Forms, the assembly is packed into an executable file that you can launch. Special header entries in the executable file identify it as a .NET program that the operating system application loader recognizes and handles accordingly. As it is executed, the MSIL code in the application’s assembly is transformed into platform-specific byte code by a just-in-time compiler (JIT compiler). This JIT compiler is launched automatically by a particular method in the assembly. All results of the JIT compilation are saved in a dynamically allocated location in memory until the application is terminated. This process runs every time an application based on the .NET Framework is started, even if it is the second instance of an application already launched. But after the first time, the applications generally start a lot faster because most of the required data is available in the main memory cache.

The JIT compiling has some advantages for code management, even if it consumes some extra resources when the Framework application is launched. The JIT compiler knows details about computer such as the particular processor design, the number of available processors, the amount of memory, and other resources. It uses that information to optimize and to adapt the application code for the target environment when it transforms the Microsoft Intermediate Language Code to platform-dependent byte code. The JIT compiler can tell whether the computer the Framework application will execute on has one processor or is a multiprocessor machine and if it is based on 32-bit or 64-bit processor design. The JIT compiler then creates the final code accordingly. If a developer starts the JIT compiler on his own computer system to pre-compile the code and later transfer the result to another target machine, the result might not be appropriate. As a conclusion, installing a pre-compiled and thus platform-dependent version of the Framework application in the target environment is not recommended.

Terminal Servers and the .NET Framework

When terminal servers are the target platform, what exactly are the requirements for .NET Windows Forms applications? Configuration data that might be necessary for the runtime behavior of the application is usually in XML format. If these configurations affect user-specific settings, they need to be managed individually. User-specific application data should be saved in the user’s home directory.

Just like conventional Windows applications, .NET programs can also access the registry, although usually they do not. They are nonetheless subject to the same rules as conventional Windows applications. To keep the system in a consistent state, you need to disable all options for user-initiated installations of .NET Windows Forms applications. On terminal servers, only administrators should have the right to install new .NET Windows Forms applications.

One recommendation for terminal servers is to pre-compile Framework applications with the JIT compiler on the target platform before a user invokes them for the first time. The Ngen.exe tool from .NET Framework SDK allows an administrator to compile the MSIL code of the assembly into platform-specific code and save it in the GAC. This needs to happen on every server where the application will be installed (for example, with a specific installation routine). However, performance improvements occur only while loading the application. On the other side, code created by the user by automatically evoking the JIT compiler is usually faster than the code created by the Ngen.exe tool.

It is best for the application's installation routine to make some of the modifications, whereas other settings must be taken into account during the application's development. Overall, the basic structure of .NET Windows Forms applications is clearly better than most conventional 32-bit applications and is certainly just as compatible with terminal servers.

But there is also a big disadvantage when using .NET applications on terminal servers. The .NET runtime environment including the just-in-time compiler has to be executed separately in the context of each individual user session. There is no shared data. This may have massive impact on resource requirements, both in terms of CPU and memory utilization.

 

Back Next

 

Read in this chapter...
6 Application Installation
6.1 Application Requirements in Multi-User Environments
6.2 Application Installation Procedures
6.3 Support Tools
6.4 Installing Sample Applications