Chapter 2: Planning the Deployment of .NET Framework-Based Applications


Once a Framework application is approved for deployment, you may be tempted to just start transferring files on to target computers. However, not all Framework applications can be deployed in the same way. Before you start on the deployment, you need to understand what exactly is going to be deployed, what your options are for deployment, and which of those options you will choose. This chapter will help you decide on the most appropriate deployment strategies for your organization, and explain the planning considerations for deploying Framework applications.

What to Deploy with the Application

Files and Folders

There are a wide variety of files that may be deployed with an application. The file types that are deployed will vary according to the nature and complexity of the application. The table on the next page lists some of the more common file types you will see deployed with a .NET-based application.

Table 2.1: Files Types that May Be Deployed with an Application

File Type

Windows Application/Service

Web Application/Service

Executable

X

X

Dynamic Link Library

X

X

.NET Configuration Files

X

X

Databases

X

X

Web Pages

X

Web Form

X

Web Service Files

X

Discovery Files for Web Services

X

XML Schema Definition Files

X

We will look at some of these file types in more detail:

Configuration Files

Configuration files are used to store information about everything from process models, through application settings, to security and authentication models. There are three main types of configuration files — Application, Machine and Security Configuration Files.

Application Configuration Files

Application configuration files contain settings specific to an application. These files contain configuration settings that the CLR reads (such as assembly binding policy, remoting objects, and so on), and settings that the application can read. The name and location of the application configuration file depend on the application's host.

For an executable file, the configuration file resides in the same folder as the executable file, and will be called <AppName>.exe.config, where <AppName> is the name of your executable (for example, MyApp.exe.config).

For Web applications, the configuration file is named web.config and resides in the virtual directory for your application. Subdirectories of your Web application can also have a web.config file, and the pages in the subdirectory are governed by both the settings contained in that specific web.config as well as the settings contained in web.config for the parent application's virtual directory. The settings contained in the configuration file in the virtual directory in which the Web files exist take precedence over the configuration file in the parent application's virtual directory if the settings conflict unless the allowOverride attribute is specified in the parent configuration file.

Note

For more information see "Hierarchical Configuration Architecture" on MSDN, see the More Information section at the end of this chapter for details.

For Internet Explorer-hosted applications, a configuration file can be referenced by the <link> tag with the following syntax:

 <link rel="ConfigurationFileName" href="<location>">. 

Note

For more information about Internet Explorer-hosted applications, see "Configuring Internet Explorer Applications" on MSDN. For further details, see the More Information section at the end of this chapter.

Machine Configuration Files

The machine configuration file, machine.config, contains settings that apply to an entire computer. This file is located in the <runtime install path>\Config directory. machine.config contains configuration settings for computer-wide assembly binding, built-in remoting channels, and ASP.NET.

Note

Many settings, such as assembly redirection, can be specified at either the application level or at the computer level. In general, you should store application settings in the application configuration files (such as web.config or the configuration file for your executable file) rather than in the machine.config file. The machine.config file stores settings for the entire computer — this can lead to an environment where settings become difficult to manage. Although this is more of a design issue than a deployment one, it is nevertheless important to bear this in mind as you plan for the deployment of your .NET-based applications.

Security Configuration Files

Security configuration files contain information about the code group hierarchy and permission sets associated with a policy level. Security configuration files are set at the Enterprise, machine, or user level. Rather than modifying the security configuration files directly, you should generally use the .NET Framework Configuration tool (Mscorcfg.msc) or Code Access Security Policy tool (Caspol.exe).

Managing Configuration Files Across Different Environments

The most difficult issue concerning the deployment of configuration files is how to manage settings for your application as you deploy to different environments. For example, if you store Web service URLs for your Web references in your application configuration file, these settings are often different in the development, test, staging, and production environments. The challenge you face is how to deploy the appropriate settings to each environment.

To manage different configuration files for different environments, you should:

  1. Add the configuration file that is used in your development environment to your Visual Studio .NET project. This file is named either web.config or app.config, depending on your application type. (Note that for ASP.NET applications, Visual Studio .NET automatically adds the web.config file to your project for you, when you create the application).

  2. Create separate configuration files for the test, staging, and production environments, in addition to the application configuration file your developers use in the development environment. Name these files so that it is immediately obvious which environment they are to be used in. For example, if you are developing a Web project, you might name your files test.web.config, stage.web.config, and production.web.config.

  3. Add each file to your project. They are then maintained in your source control system.

  4. Include only the file you need for the specific environment to which you are deploying, and rename it to the required name as part of the deployment. The required name is either web.config for ASP.NET applications, or <AppName>.exe.config for Windows applications. You could deploy all of the other configuration files along with your application and it does not affect your application in any way. However, because these files are not actually needed, you should avoid deploying them along with the application for efficiency.

Note

Visual Studio .NET 2003 allows you to automate the process of deploying the correct configuration file with your application, if you use Microsoft Windows Installer packages to deploy the application. For more detail see Chapter 3, "Implementing the Deployment of .NET Framework-based Applications."

The deployment process used to install your application to the test environment should be as similar as possible to the process you use to deploy to the production environment. If you are deploying different configuration files to these environments, this raises the issue that the deployment of the production configuration file will not be fully tested before your roll out your application.

One approach to solving this issue is to actually deploy the production version of your configuration file to the test environment, rather than the test version. That way, you can ensure that it is distributed correctly. Your testers can then perform the supplementary task of replacing the production version of the configuration file with the test version before running the application in the test environment. This should be a separate step, in order to avoid introducing unanticipated issues into the deployment process.

Specifying Remoting Information

One important piece of information that can be contained in configuration files is remoting information. Remoting in .NET-based applications allows different applications to communicate with one another, whether they reside on the same computer, on different computers in the same local area network (LAN), over a wide area network (WAN) link or the Internet. The applications can even be running on different Microsoft operating systems. The .NET Framework provides a number of services such as activation and lifetime control, as well as communication channels responsible for transporting messages to and from remote applications.

If you are deploying a distributed .NET-based application, remoting information will provide the application with the information necessary for it to function properly. To configure remoting, create a remoting configuration section and include it in your application's configuration file, web.config file, or machine.config file. You then need to ensure that the appropriate configuration file is deployed along with your application.

You must provide the following information to the remoting system to make your types remotable:

  • The kind of activation required for your type.

  • The complete metadata describing your type.

  • The channel registered to handle requests for your type.

  • The URL that uniquely identifies the object of that type. In the case of server activation, this means a URL that is unique to that type. In the case of client activation, a URL that is unique to that instance will be assigned.

Note

For more information about the remoting elements you can use in your configuration file, see "Remote Object Configuration" on MSDN.

Remoting information can also be specified directly in your client and server code. For more information on this, see "Programmatic Configuration" on MSDN.

Web Services Files

Many of the issues affecting the deployment of Web applications also apply to Web service deployment — IIS settings may need to be deployed with the Web service, as could HTTP handlers and modules.

One slight difference between the deployment of Web services and the deployment of Web applications is that you are deploying the Web service file (.asmx) rather than Web forms (.aspx). A Web service may also have one or more dependencies in the form of dynamic link libraries (*.dll) which will also need to be deployed.

Discovery Files

For developers to take advantage of existing Web services, they must query the Web Service Description Language (WSDL) contained in the Web service file. However, before they can do this they must be aware of the existence of Web services and be able to contact them. In reality, developers do not always know what Web services are available. Therefore, they are not able to access the Web service description unless you provide them with a discovery mechanism. That is where discovery files come in. You can provide a discovery mechanism for Web services by creating and deploying a static discovery file (.disco) with the Web service. Developers can then use this discovery file when they add a Web reference to their applications — they can view the contents of the file in the Add Web Reference dialog box provided by Visual Studio .NET and can link to the WSDL for your service from this file.

You can create static discovery files by browsing to your Web service and appending the "?DISCO" query string to the URL (for example, http://www.somedomainname-123.com/somewebservice.asmx?DISCO). The resulting XML can be saved as a .disco file. The following example illustrates the contents of a static discovery file for the counter Web service:

 <?xml version="1.0" encoding="utf-8" ?> <discovery xmlns:xsd="http://www.w3.org/2001/XMLSchema"             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"             xmlns="http://schemas.xmlsoap.org/disco/">   <contractRef ref="http://www.contoso.com/Counter.asmx?wsdl"                 docRef="http://www.contoso.com/Counter.asmx"                 xmlns="http://schemas.xmlsoap.org/disco/scl/" />     <soap address="http://www.contoso.com/Counter.asmx"         xmlns:q1="http://tempuri.org/"         binding="q1:CounterSoap"         xmlns="http://schemas.xmlsoap.org/disco/soap/" /> </discovery> 

The location of the actual discovery information is contained in the <contractRef> element — developers referencing your Web service in Visual Studio .NET can click a link in the Add Web Reference dialog box to view the contract for somewebservice (that is, the WSDL for your Web service).

Note

If you create your discovery files in this way as a predeployment step by using your development servers, you need to update the URLs in both the ref and the docref attributes of the <contractRef> section before you deploy them to your production servers, so that they point to the live Web services and not the development ones.

Once you have created the initial discovery file, you can update it to contain references to additional Web services. In this case you simply need to include the <contractRef> element with the discovery file for each Web service that you want to allow developers to discover. When they browse to your discovery file using the Visual Studio .NET Add Web Reference dialog box, they will see contract links for each <contractRef> element. A simple way to add these elements to your DISCO file is to simply browse to each of your Web services with the "?DISCO" query string, and then copy and paste the <contractRef> element into the discovery file.

In many cases it may be appropriate to build a DISCO file that advertises all of the Web services you wish to make available on your server, and deploy that to the Web server's root directory. That way developers will always know where to go in order to see what Web services are available on a particular server. You may also wish to modify the default document for the Web server (usually Default.htm, Default.asp, or Default.aspx) so that it indicates the presence of a discovery file and its location.

After you create your DISCO file, you need to deploy it to the production environment. Because the discovery file is a simple XML-based text file, it does not have any special deployment requirements — it can deployed to the appropriate location on the production Web server with simple copy operations (such as XCOPY or FTP), or it can be included in a Web setup Windows Installer file.

Note

Discovery can also be achieved with a process known as dynamic discovery. If you create your Web services with Visual Studio .NET, a dynamic discovery file (.vsdisco) is created for you. ASP.NET can use this file to perform a search through all subfolders in your Web service virtual directory to locate and describe Web services. You should not deploy this file to the production environment, because you will lose control over which Web services can be discovered by other developers — you should use this file only on development computers.

XML Schema Definition (XSD) Files

XML Schemas are documents that are used to define and validate the content and structure of XML data, just as a database schema defines and validates the tables, columns, and data types that make up a database. XML Schemas are stored in XML Schema Definition (XSD) files.

You only need to deploy XSD files in when your application or service needs to access the XML Schema. A common example of this is for XML Web Services. XML Web Services can pass data in the form of XML datasets, and in some cases, the dataset will include information about the structure of the data from the schema, and is known as a typed dataset.

If you are deploying an XML Web Service, and that Web service returns typed datasets, you also need to deploy the corresponding XSD file, as the WSDL (and hence the DISCO file) for your Web service will contain references to the XSD files that define the schemas for those datasets. When developers browse to your DISCO file from the Add Web Reference dialog box in Visual Studio .NET, they will be able to access the dataset schema definition by clicking on the View Schema link.

J# Redistributable Package

If your application utilizes J#, then you will also need to deploy the Visual J# .NET Redistributable Package (vjredist.exe). Applications and controls written using the Microsoft Visual J# development tool require the Visual J# .NET Redistributable Package to be installed on the computer where the application or control runs.

The Visual J# .NET Redistributable Package is available from the Visual J# media or by Web download from http://msdn.microsoft.com/vjsharp. The .NET Framework must already be installed if you are going to install Visual J# .NET Redistributable Package.

The Visual J# .NET Redistributable Package supports all platforms supported by the redistributable package for the .NET Framework. The Visual J# .NET Redistributable Package has no additional system requirements over and above the requirements of the redistributable package for the .NET Framework. The setup program of the Visual J# .NET Redistributable Package installs the same files on all supported platforms to support both server and client scenarios.

Note

The Visual J# .NET Redistributable Package is not intended to run applications written with other Java-language development tools. Applications and services built with Visual J# .NET will run only on the .NET Framework and will not run on any Java Virtual Machine.

Assemblies

Assemblies are the building blocks of .NET Framework applications; they form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions. An assembly is a collection of types and resources that are built to work together and form a logical unit of functionality. An assembly provides the common language runtime with the information it needs to be aware of type implementations. To the runtime, a type does not exist outside the context of an assembly. Assemblies can contain up to four different elements:

  • The assembly manifest - every assembly, whether static or dynamic, contains a collection of data that describes how the elements in the assembly relate to each other. The assembly manifest contains this assembly metadata. An assembly manifest contains all the metadata needed to specify the assembly's version requirements and security identity, and all metadata needed to define the scope of the assembly and resolve references to resources and classes. The assembly manifest can be stored in either a Portable Executable (PE) file (an .exe or .dll) with Microsoft intermediate language (MSIL) code, or in a standalone PE file that contains only assembly manifest information.

  • Type metadata - defines the types that the assembly contains (much as type libraries do for COM objects).

  • MSIL code - implements the types you have defined. MSIL is a language used as the output of a number of compilers and as the input to a just-in-time (JIT) compiler. The common language runtime includes a JIT compiler for converting MSIL to native code.

  • Resources - could include graphics or localized strings.

You can group all of these elements together in a single file, such as a .dll or an .exe. Alternatively, you can have different elements of your assembly reside in separate files. For example, you might want large graphics or seldom used types to reside in separate files — that way they will only be loaded when required. For this scenario, your PE file that resides within the assembly (.dll or .exe) will contain the assembly manifest and core MSIL code and type metadata, and the assembly manifest will link to the external resource file(s) for graphics and to compiled .NET module(s) for seldom-used types and their MSIL implementation.

Note

For information on how the CLR determines which assembly to load, see Chapter 4, "Maintaining .NET Framework-Based Applications."

Strong Naming Assemblies

In cases where you want to be sure that an assembly is unique, you may choose to provide it with a strong name. Strong names consists of the assembly's identity — its simple text name, version number, and culture information (if provided) — plus a public key and a digital signature. The name is generated from an assembly file (the file that contains the assembly manifest, which in turn contains the names and hashes of all the files that make up the assembly), using the corresponding private key.

Note

For a strong name to be secure, you must make sure that you keep the private key corresponding to the name secure.

Strong names provide the following features:

  • Name uniqueness. They rely on digital signatures to establish unique identities.

  • Protection of the version lineage of an assembly. A strong name can ensure that no one else can produce a subsequent version of your assembly, unless you provide them with the source code and the private key. Users can be sure that the version of the assembly they load comes from the same publisher that created the version the application was built with.

  • Differentiation by the CLR between the versions of an assembly. This allows the appropriate version to be used by the referencing application.

  • Integrity check by the CLR against the digital signature. This ensures that the file has not been tampered with.

Note

You can strong name any assembly. However, any assembly that will be placed in the global assembly cache (GAC) must be strong named. For more information on the global assembly cache, see the Shared Assemblies section later in this chapter.

Note

Although a strong named assembly is signed, there is no requirement for the publisher to prove its identity to a third party authority. You can use the signcode.exe utility to make this a requirement for any assembly, regardless of whether it is strong named. For more information, see Assembly Security Considerations on MSDN.

By default, any application that calls a strong named assembly needs to be fully trusted, anything less than that and the assembly will not be run. The trust level of an application is defined in the application config file, or determined by the application running in a particular zone in Internet Explorer. If you wish an application to call a strong named assembly, you need to either ensure that the application is fully trusted, or modify the assembly to allow calls from partially trusted applications. This is achieved by adding the AllowPartiallyTrustedCallersAttribute Class to the assembly.

Note

There are security implications to using the AllowPartiallyTrustedCallersAttribute Class. For more information on the security implications of using this, see AllowPartiallyTrustedCallersAttribute Class

Another significant issue with using strong assemblies comes when they need to be updated. The version number of the assembly must be included when an application references a strong-named assembly, this means that if a new assembly is simply added using a file copy technique, the application will not just start using the new assembly. For more information on this and how to deal with it, see Chapter 4, "Maintaining .NET Framework-based Applications."

To give an assembly a strong name, you can use the Sn.exe tool to create a public/ private key pair, and then strong name your assembly by setting the Assembly attributes of the Application project in Visual Studio .NET 2003. Alternatively, you can use the assembly linker utility (Al.exe) to strong name your assembly with the keys generated by Sn.exe after they are built. This latter approach is most useful if you need to delay the signing of your assemblies until after you have compiled the assembly for security reasons. When you delay the signing of your applications, you can build and test an assembly with only the public key. The private key can then be applied later when the assembly is due to be actually deployed.

Note

For more information on delaying the signing of assemblies see Delay Signing of an Assembly MSDN.

For more information about strong naming your assemblies with attributes, see "Signing an Assembly with a Strong Name" on MSDN.

Private Assemblies

If an assembly is designed for the sole use of your application, you should deploy it as a private assembly. Private assemblies are usually deployed directly to the application base directory. The application base directory can be any of the following:

  • The directory or subdirectory that contains the executable, if you have built a Windows Forms-based application.

  • The bin folder located in the virtual directory, if you have built an ASP.NET Web application.

  • The location specified in the <codebase> element of the application configuration file.

In most cases, you should deploy private assemblies to the application base directory as this is the first place that the CLR looks for these assemblies if they are not specified in the application configuration file.

Private assemblies are used only by the application for which they were developed, allowing for your application to be isolated from other applications. This helps to avoid problems with different versions of the same DLL being installed by different applications, and preventing one or more applications functioning properly — a situation commonly referred to as DLL hell.

Shared Assemblies

In some cases the same assemblies are required by different applications. If this is the case for your applications, you have three deployment choices:

  • Deploying the assembly with each application.

  • Deploying the assembly in one directory and directing each application to use it.

  • Deploying the assembly in the global assembly cache.

We will discuss each of these in turn:

Deploying the Assembly with Each Application

If you deploy the assembly with each application, you would generally deploy the assembly in the same directory as the application. In this case each copy of the assembly is considered to be independent from the others.

Deploying the same assembly multiple times introduces some considerations you should be aware of. It is possible to run multiple versions of the assembly on the same computer, including those compiled under different versions of the Framework. This can be important if you are going to run multiple Framework applications side by side on a computer. However, running multiple versions of an assembly can introduce version control problems. If there is security issue with a particular assembly you may have to update the same assembly multiple times. This may give you significant management difficulties, depending on the deployment strategy you choose. It is therefore very important to ensure that you are fully aware of where the different copies of the assembly are installed.

Note

For more details on running applications side by side see Chapter 4, "Maintaining .NET Framework-based Applications."

Deploying the Assembly in One Directory

If you wish, you can place your assembly in one directory and direct each application to use it by modifying the <codebase> entry in each application config file, pointing to the location of the assembly in question.

If you use a single directory for your assemblies you lose the ability to run multiple versions of the assembly side by side. However with just a single copy of the assembly in place, you eliminate version control issues.

You should think carefully before deploying your assemblies to a single directory in this way, as there may be future situations where side-by-side operation becomes important, forcing you to change your deployment strategy at that time.

Deploying the Assembly in the Global Assembly Cache

The global assembly cache is a special location on computers running the Framework that allows multiple versions of the same assembly to reside side by side. Installing your assemblies into the global assembly cache provides the following advantages:

  • A central point to distribute and manage code that is installed on the machine. Depending on your deployment strategy, it can be much easier to simply add a new version of a component to the global assembly cache than it is to update many copies that happen to be installed in numerous private application directories.

  • Support for side-by-side installation of components and the Framework. For more details, see Chapter 4, "Maintaining .NET-Framework Based Applications."

  • Better performance on loading strong-named assemblies. This is because signature verification is done on installation into the global assembly cache, whereas for private assemblies the check occurs on each assembly load.

  • Better performance on loading multiple copies of assemblies. This is because multiple ASP.NET applications that load the same assembly will all map to the same in memory copy of the assembly if it was loaded from the global assembly cache. If that same assembly was loaded from the application directory, multiple copies of the assembly would be loaded in memory.

However, installing an assembly into the global assembly cache introduces the following issues that are not encountered with other assemblies:

  • Installing an assembly into the global assembly cache requires administrative privileges by default, because the physical location of the global assembly cache is a subfolder of the Windows directory.

  • Assemblies in the global assembly cache must be created with a strong name because the CLR performs integrity checks on all files that make up shared assemblies based on the strong name. The cache performs these integrity checks to ensure that an assembly has not been tampered with after it has been created (for example, to prevent a file from being changed without the manifest reflecting that change).

  • You cannot simply copy an assembly into the global assembly cache and have your applications use it. The assembly must be installed in the global assembly cache. This can be done by using Windows Installer technology or by using the Gacutil.exe tool.

Do not assume that just because an assembly is required by multiple applications it should always be installed in the global assembly cache. The strategy you choose for deploying shared assemblies will depend on the specific requirements of your applications, but also the overall deployment strategy you use. Specifically, if you choose a no-touch deployment approach, using multiple private assemblies is usually more appropriate. For more details, see the No-Touch Deployment section later in this chapter.

In a production environment, you should always install assemblies into the global assembly cache with some mechanism that can maintain a count of the number of references to that assembly. This prevents premature removal of the assembly from the global assembly cache by the uninstall routine of another application, which would break any application that relies on that assembly. There are two ways to achieve this — using Windows Installer packages to install your assemblies into the global assembly cache, or by using the gacutil.exe tool with the /ir switch to add a traced reference. If you install an assembly using gacutil.exe, you should also use the same tool to remove it, this time with the /ur switch.

It is theoretically possible to add assemblies into the global assembly cache by dragging and dropping them into the cache Windows Explorer. However, this does not implement reference counting and should be avoided.

Note

Reference counting is only useful if it is always implemented. Any assembly that is installed without using reference counting will cause the reference count for that assembly to be inaccurate.

If you are developing components that may be used by other developers, you should always create strong names for them. That is because you do not know when you develop your assembly whether the other developers will wish to install the assembly in the global assembly cache. The other developer should not apply a strong name to your assembly after you create it, because then it cannot be verified that you (or your company) is the author of the component.

Note

The CLR attempts to locate assemblies in the global assembly cache before searching in the application base folder. Consequently, if you deploy a strong named private assembly with your application but it is already present in the global assembly cache, the CLR uses the shared version, rather than the private one, at run time. This should not lead to any problems, because assemblies with the same strong name should always be identical.

For more information about specifying assembly locations, see "Specifying an Assembly's Location" on MSDN.

For more information about how the CLR locates assemblies, see "How the Runtime Locates Assemblies" on MSDN.

For more information about redirecting assembly binding, see "Redirecting Assembly Versions" on MSDN.

Windows Forms User Controls

As mentioned in Chapter 1, Windows Forms user controls are assemblies referenced from Web pages that are downloaded to the user's computer and executed upon demand. Windows Forms user controls can present particular deployment challenges because they run in the security context of the browser.

From a code access security perspective, there are two types of Windows Forms user controls: those that are run under the default security policy and those that require higher trust. To write Windows Forms user controls that are intended to run under the default security policy, you only need to know which operations are allowed by the default security policy for the intranet or the Internet zones, depending on where the CAB file is deployed. As long as a Windows Forms user control does not require more permission to execute than it receives as a result of its zone of origin, then it will run. To execute managed controls that demand higher trust, the administrator or user must adjust the security policy of any computer that runs the code.

Controls that require higher trust should always be strong named or signed with a publisher certificate. This allows policy administrators to grant higher trust to controls signed with a particular certificate without reducing their security with regard to other intranet/Internet code. After the assembly is signed, the user must create a new code group associated with sufficient permissions, and specify that only code signed by the user's company or organization be allowed membership to the code group. After the security policy is modified in this manner, the control has sufficient permission to execute.

Because security policy must be modified to allow high trust downloaded controls to function, deploying this type of control is much easier on a corporate intranet than on the Internet — there is usually an enterprise administrator who can deploy the described policy changes to multiple client computers on the intranet. In order for high-trust controls to be used over the Internet by general users, the user must be comfortable following the publisher's instructions to modify the policy and to allow the high-trust control to execute. Otherwise, the control will not run.

For more information on using Windows Forms user controls in Web applications see "Host Secure, Lightweight Client-Side Controls in Microsoft Internet Explorer" on MSDN.

Installation Components

Distributed .NET applications consist not only of traditional program files and assemblies, but also of associated resources, such as message queues, event logs, performance counters, and databases. These elements need to be created as part of your deployment process. The .NET Framework provides installation components that allow application resources to be created and configured when your application is installed, and removed when your application is uninstalled. These installation components integrate with widely available deployment tools, such as Installutil.exe, Windows Installer files (.msi), and the Windows Installer service. There are two types of installation components: predefined installation components and installer classes.

Predefined Installation Components

Microsoft supplies five predefined installation components that can be used with applications. These are:

  • EventLogInstaller - used to install and configure event logging.

  • MessageQueueInstaller - used to install and configure message queues..

  • PerformanceCounterInstaller - used to install and configure performance counters and monitoring.

  • ServiceInstaller and ServiceProcessInstaller - used to install and configure Windows Services.

Each of these installation components are used by the application designer to ensure that the correct application resources are installed at deployment time. If application designers wish to use any of these application resources, they should include and configure the corresponding predefined Installation component in a Visual Studio .NET 2003 application project. When the component is added, this also adds an associated class, called ProjectInstaller to the project, which is used to install the component. The developer can then compile the project to a dll or an exe file, ready to hand off to deployment.

Then when the install occurs, the deployment project runs the ProjectInstaller class, which in turn launches the installation process for each of the components. By using a proper installation process for these resources, you ensure that all the appropriate settings, such as specific registry settings are installed for each component. The installation component also accesses the resource itself in order to retrieve the properties of that resource (for example maximum queue size and journal recording settings in the case of a message queue). When you deploy your project to the production environment, it recreates the resource from your development environment and ensures that those settings are applied. All of these settings are stored in the code for the installation component — this happens automatically, so you do not need to manage the settings manually.

Note

You do not have to create and configure application resources in your development environment. If you wish, you can access the installation component directly in the ProjectInstaller class (or any class with the RunInstallerAttribute value set to true) and manually set the necessary values to create and install the resource in the state you desire.

For details on deploying pre-defined installation components, see Chapter 3, "Implementing the Deployment of .NET Framework-based Applications."

Installer Classes

In some cases you need to add application resources for which there are no corresponding predefined installation components. You can add installer classes to your .NET-based application to perform specific actions during installation. For example, you can use installer classes to create databases required for your application, or you can use them to precompile a certain assembly to native code after the main installation is complete.

Instrumented Assemblies

One example of an application resource that needs to be added using installer classes is an instrumented assembly. Instrumented assemblies integrate with Windows Management Instrumentation (WMI).

Instrumented assemblies need to undergo a registration stage, in which its schema can be discovered and registered in the WMI repository. Schema publishing is required on a per assembly basis. Any assembly that declares instrumentation types (events or instances) must have its schema published to WMI.

As with other application resources, it is the responsibility of the application developer to make sure that instrumented assemblies are installed successfully. If the project already contains a predefined installation component, you should use the ManagementInstaller class for your instrumented assembly. However, no predefined installation components have been added, the developer must add an installer class, the DefaultMangementProjectInstaller class, to the project. Then the developer can compile the assembly ready for deployment.

For more information about registering WMI schemas for your instrumented applications with the ManagementInstaller class, see "Registering the Schema for an Instrumented Application" on MSDN.

For information on deploying instrumented assemblies, see Chapter 4, "Maintaining .NET Framework-Based Applications."

COM Components

Applications built completely on the .NET platform will eventually replace those developed with COM. However, until then, your developers may need to use or create COM components with Visual Studio .NET 2003.

COM objects that interoperate with your Framework applications must be registered on the target computer. Similarly, COM+ components that interact with your .NET-based applications must be properly installed into the COM+ catalog.

The main challenge in deploying COM components comes in ensuring that these components can communicate with .NET-based assemblies. This is because .NET-based assemblies are managed code and COM components are unmanaged code.

The interoperability features of .NET, known as COM Interop, allow you to work with existing unmanaged code in COM components along with Microsoft Win32 application programming interface DLLs. It also allows you to use managed components from your unmanaged, COM-based code.

When a .NET component is called from COM, the runtime generates a wrapper object to bridge the gap between the managed and unmanaged environments. In this case, the runtime reads the type information for the component from its assembly metadata and generates a compatible COM callable wrapper (CCW). The CCW acts as a proxy for the unmanaged object.

When a COM object is called from .NET, the runtime generates a runtime callable wrapper (RCW). Similar to the CCW, the RCW acts as a proxy between the managed .NET code and the unmanaged COM code. RCW and CCW are created at run time and so are not deployment issues. However, the RCW is created from type information that is stored in an interop assembly, which does need to be deployed with your application.

Note

For more information on COM wrappers, see the COM Wrappers section of the .NET Framework Developers Guide. For further details see the More Information Section at the end of this chapter.

An interop assembly, unlike other .NET assemblies, contains no implementation code. Interop assemblies contain only the type definitions of types that are already implemented in COM components. It is from these type definitions that the CLR generates the RCW to allow managed code to bind to the types at compile time and provides information to the CLR about how the types should be marshaled at run time.

There are two types of interop assemblies:

  • Primary interop assemblies (PIAs) - These are interop assemblies that are provided by the same publisher as the type library they describe, and they provide the official definitions of the types defined with that type library. They are always signed by their publisher to ensure uniqueness.

  • Alternate interop assemblies - These are any assembly that is not a PIA. They are not signed by the COM object publisher.

You should always use PIAs if they are available. This is because PIAs uniquely identify a type. Types defined within an interop assembly that is not provided by the component publisher are not compatible with types defined in the PIAs. For example, consider two developers in the same company who are writing managed code that will interoperate with an existing third-party supplied COM component. One developer acquires the PIA from the component publisher. The other developer generates his or her own interop assembly by running Tlbimp.exe against the COM object's type library. Each developer's code works properly until one of the developers tries to pass the object to the other developer's code. This results in a type mismatch exception; although they both represent the same COM object, the type checking functionality of the CLR recognizes the two assemblies as containing different types.

A PIA is created from a type library by running the TlbImp.exe utility with the / primary switch. If you do not have a PIA, alternative interop assemblies can be created by Visual Studio .NET 2003 (by setting a reference to a COM object) or by using Tlbimp.exe. If you use Visual Studio .NET to create a reference to a COM object, Visual Studio .NET looks in the registry to see if a PIA is registered on that computer for the COM object being referenced. If one is registered, it uses the PIA instead of generating one. If there is no PIA, Visual Studio .NET creates an alternative interop assembly.

Note

The Type Library Importer (Tlbimp.exe) converts most COM method signatures into managed signatures. However, several types require additional information that you can specify by editing the interop assembly. For more information about Tlbimp.exe, see "Type Library Importer (Tlbimp.exe)" on MSDN.

All PIAs are strong named. Alternate interop assemblies do not have to be, and if they are generated by creating a reference to a COM object in Visual Studio .NET 2003, they will not be strong named. If you want a strong named alternate interop assembly, you must manually create it, strong name it, and then set a reference to it. The interop assembly will vary according to the platform on which it is created, so you may have to create multiple interop assemblies depending on the platforms to which you will be deploying the assemblies.

Note

Several of the Windows system .dlls do not ship with Primary Interop Assemblies. If you wish your managed code to interact with these .dlls, you will need to create interop assemblies for this purpose.

For more information on deploying COM components and interop assemblies, see Chapter 3, "Implementing the Deployment of .NET Framework-based Applications."

For more information about proxies, see "Deploying Application Proxies" on MSDN.

Serviced Components

.NET components rely on COM+ to provide them with component services such as transaction management, object pooling, and activity semantics. A .NET component that uses COM+ services is known as a serviced component.

Because your serviced components are hosted by a COM+ application, they must be accessible to that application. This introduces the following registration and configuration requirements for the serviced component:

  • The assembly must be strong-named.

  • The assembly must be registered in the Windows registry.

  • Type library definitions for the assembly must be registered and installed into a specific COM+ application.

Serviced components can often register dynamically the first time they run. The first time a client attempts to create an instance of a serviced component, the CLR registers the assembly, the type library, and configures the COM+ catalog. Registration occurs only once for a particular version of an assembly. This is the easiest method for registering your serviced components, but it works only if the process running them has administrative privileges. Also, any assembly that is marked as a COM+ server application requires explicit registration, and dynamic registration does not work for unmanaged clients calling managed serviced components.

In many cases, the process that uses your assembly will not have the required privileges for dynamic registration. For example, if the assembly is used in a Web application, ASP.NET is not able to register your serviced component. ASP.NET does not run with administrative privileges by default (unless you set it to run as SYSTEM, which is not recommended for security reasons) so when your serviced component attempts to register, it will fail with an access denied exception. Under these circumstances you will need to ensure that the registration occurs at deployment time. For more information on how to achieve this, see Chapter 4, "Implementing the Deployment of .NET Framework-based Applications."

As serviced components take advantage of COM+ services, they have some of the same deployment considerations as COM+ components. These include:

  • Any communication with the COM+ application occurs using DCOM by default, so you need to deploy interop assemblies to client computers just as you would for a traditional COM components.

  • In addition to any COM+ settings that can be set using attributes on the assemblies themselves, you must make sure other configuration settings (such as adding users to roles and setting the process security identity) are created and assigned correctly. This can be achieved by adding a script to the custom action that registers the component.

Note

You can configure a COM+ application to use SOAP rather than DCOM. This circumvents the need to deploy interop assemblies. However, this approach does not allow you to flow transaction context from client to server. You would need to initiate your transaction at the remote serviced component.

IIS Settings

ASP.NET applications require IIS in order to run. In some cases you will need to alter the settings of IIS to allow applications to run, or to control the environment in which they run. When you install ASP.NET on a server running Windows Server 2003, ASP.NET applications are executed by IIS 6.0.

IIS 6.0 runs in one of two distinct modes of operation, known as application isolation modes. These modes are:

  • Worker process isolation mode (the default)

  • IIS 5.0 isolation mode

When ASP.NET runs in the worker process isolation mode, it runs in the W3wp.exe worker process. In this case, the process model built into ASP.NET is disabled, and the worker process isolation architecture of IIS 6.0 is used instead. In worker process isolation mode, you can isolate anything — from an individual Web application to multiple sites — in its own self-contained World Wide Web Publishing Service (WWW service) worker process, preventing one application or site from stopping another. The processes are also completely separated from the core WWW service, Inetinfo.exe. Because these Internet Server (ISAPI) applications run separately from the WWW service, an application failure prevents all services hosted by the WWW service from failing. Only the worker process that hosts the ISAPI application is affected. Worker processes can be configured to run on specific CPUs, which allow you greater control of balancing system resources. Plus Web applications run with the Network Service identity, which provides a security advantage: the Network Service account has lower access privileges than LocalSystem.

If you configure IIS 6.0 to run in IIS 5.0 isolation mode, ASP.NET runs in its own process model, Aspnet_wp.exe, and uses its own configuration settings. When IIS 6.0 is in IIS 5.0 isolation mode, the worker process isolation architecture of IIS 6.0 is disabled and the process model build into ASP.NET is used for all ASP.NET applications on the computer.

You must use IIS 5.0 isolation mode for applications that conflict with worker process isolation mode until the applications are modified. The following application characteristics conflict with worker process isolation mode:

  • Dependency on Inetinfo.exe. If the application must run in the Inetinfo.exe process, it must be run in IIS 5.0 isolation mode because applications do not run in Inetinfo.exe in worker process isolation mode.

  • Requires Read Raw Data Filters. Read Raw Data Filters are available in IIS 5.0 isolation mode only.

  • Requires Dllhost.exe. Applications that must be run in a Dllhost.exe environment can be run only in IIS 5.0 isolation mode because Dllhost.exe is not available in worker process isolation mode.

If the IIS 6.0 service is running in worker process isolation mode (the IIS 6.0 default mode), and you must run applications that do not meet the requirements for worker process isolation mode, you will need to switch to IIS 5.0 isolation mode. This means you will not be able to take advantage of worker process isolation and the other features of worker process isolation mode.

In IIS 5.0, settings for ASP.NET applications were stored in the <processModel> element of the machine.config file. This is still the case if you run the IIS 6.0 service in IIS 5.0 isolation mode. However, if you use IIS 6.0 in worker process isolation mode, only 3 settings in the <processModel> element are honored. These are:

  • maxWorkerThreads

  • maxIoThreads

  • responseDeadlockInterval

All other settings are ignored. In some cases the other settings are irrelevant for IIS 6.0, but for others, there is an equivalent setting which should be specified in the IIS 6.0 metabase. For information on this, see "Mapping ASP.NET Process Model Settings to IIS 6.0 Application Pool Settings" on MSDN.

Note

For more information on the architectural differences between IIS 5.0 and IIS 6.0, see the "Technical Overview of Internet Information Services (IIS) 6.0" white paper.

HTTP Handlers and HTTP Modules

ASP.NET provides IHttpHandler and IHttpModule interfaces that allow you to use application programming interfaces (APIs) that are as powerful as the ISAPI programming interfaces available with IIS, but with a simpler programming model. HTTP handler objects are functionally similar to IIS ISAPI extensions, and HTTP module objects are functionally similar to IIS ISAPI filters.

ASP.NET maps HTTP requests to HTTP handlers. Each HTTP handler enables processing of individual HTTP URLs or groups of URL extensions within an application. HTTP handlers have the same functionality as ISAPI extensions with a much simpler programming model.

An HTTP module is an assembly that handles events. ASP.NET includes a set of HTTP modules that can be used by your application. For example, the SessionStateModule is provided by ASP.NET to supply session state services to an application. You can also create custom HTTP modules to respond to either ASP.NET events or user events.

To deploy HTTP handlers and HTTP modules you need to first deploy the corresponding .NET class in the \bin directory under the application's virtual root and then registering the HTTP handler or module under in the web.config configuration file.

For more information about working with and registering HTTP handlers and HTTP modules, see "HTTP Runtime Support" on MSDN.

SSL Settings

The SSL features in IIS cannot be used until a server certificate is obtained and bound to the Web site. For Internet (public) applications, you obtain a server certificate from a recognized third-party certification authority. For private (intranet) applications, you can issue a server certificate yourself. IIS associates the certificate with a particular IP address and port number combination.

You need to determine a way to bind your server certificate to your production Web site as you deploy your ASP.NET application. The most common way to do this is to manually bind the certificate using the IIS management console. If all of the virtual directories and Web sites on your Web server can use the same certificate, you can bind a server certificate at the Master Properties level for your Web server — this binds the certificate to every Web site that has not previously been bound to a certificate. If this is your first server certificate, it means that it is effectively bound to the entire Web server. Any new virtual directories or Web sites that you create as part of your deployment routines are bound with that server certificate.

For more background information about using SSL, see "Untangling Web Security: Getting the Most from IIS Security" on MSDN.

Note

ASP.NET is not available on Windows XP 64-Bit Edition and the 64-bit versions of the Windows Server 2003 family.

Registry Settings

.NET-based applications should be less reliant on registry entries than previous applications. For example, assemblies do not require registry entries, unlike COM components in the past. However, your application might still rely on registry settings in some cases. These include:

  • If your application includes pre-.NET based components such as COM, COM+, or Windows Services.

  • If your assemblies must communicate with a COM component or pre-.NET services (The registry entries occur when you register the assembly during installation).

  • If you wish to add registry entries to provide information such as licensing or versioning.

Registry entries may also be added by installation components.

For more information about deploying registry settings with Windows Installer files, see Chapter 3, "Implementing the Deployment of .NET Framework-based Applications."

Merge Modules

Merge modules are reusable setup components. They cannot be installed directly — instead they are merged into a Windows Installer package for each application that uses the component. Much as dynamic-link libraries allow you to share application code and resources between applications, merge modules allow you to share setup code between Windows Installer files. This ensures that the component is installed consistently for all applications, eliminating problems such as version conflicts, missing registry entries, and improperly installed files. Merge modules may also be used to deploy third-party components as part of your application deployment.

Merge modules can only be used in conjunction with Windows Installer files and cannot be deployed in any other way.

For more details on creating and deploying merge modules see Chapter 3, "Implementing the Deployment of .NET Framework-based Applications."

For more information about merge modules, see "Introduction to Merge Modules" on MSDN.

CAB Files

CAB files provide a means of packaging together the files needed by an application so that they can be distributed and installed more easily.

Creating CAB files provide the following advantages:

  • They can be downloaded and any managed controls that they contain can be extracted and executed upon demand.

  • They support a number of compression levels, allowing for a quick download time.

  • You can use Microsoft Authenticode technology to sign your CAB files so that users will trust your code.

  • They have zero client footprint (with the exception of the download cache).

  • They contain controls that can easily be updated simply by repackaging the new version into a CAB and replacing the existing copy on the Web server. The CAB projects support versioning, so you can ensure that end users are always using the most recent copy.

In some cases you may need to deploy CAB files that have been created for other applications. In others you may choose to create CAB files yourself to support the distribution option you have chosen for your application.

For more details on creating and deploying CAB files, see Chapter 3, "Implementing the Deployment of .NET Framework-based Applications."

For more information about managing the security requirements for downloaded CAB files, see "Writing Secure Managed Controls" on MSDN.

Localization

The CLR provides support for retrieving culture specific resources that are packaged and deployed in satellite assemblies. Satellite assemblies contain only resource files, or loose resources such as .gif files. They do not contain any executable code.

In the satellite assembly deployment model, you create an application with a default assembly (the main assembly) and several satellite assemblies. You should package the resources for the default language neutral assembly with the main assembly and create a separate satellite assembly for each language that your application supports. Because the satellite assemblies are not part of the main assembly, you can easily replace or update resources corresponding to a specific culture without replacing the application's main assembly.

Note

If your main assembly uses strong naming, satellite assemblies must be signed with the same private key as the main assembly. If the public/private key pair does not match between the main and satellite assemblies, your resources will not be loaded.

If you have many different languages for which you need to localize your application, you can streamline the packaging and deployment process by:

  • Packaging your core, language neutral files into a merge module (MSM) using a Visual Studio .NET setup and deployment project.

  • Creating a project that contains the localized resources for all languages that you want to support.

  • Creating a separate Windows Installer file for each language you are supporting, using Visual Studio .NET setup and deployment projects. This allows you to localize the installer as well as the application.

  • Creating a base installer file for the primary language you wish to support and then creating transforms for each additional language that you wish to support.

  • Adding the output for the project that contains the localized resources into each Windows Installer project. That essentially includes all of the localized resources. You can then use the ExcludeFilter to filter out all but the one localized resource that you need for your specific language.

As an alternative, instead of filtering out the localized resources that are not needed, you can simply distribute them all. That way, your clients can use the different localized resources on the same computer; for example, they can change their locale settings and have the appropriate resources loaded by your application.

Another approach is to create a core installer and a separate set of localized installers (typically known as language packs). Your global customers can then install your core application and then one (or more) of your language packs.

Note

For more information Satellite Assemblies, see "Creating Satellite Assemblies" on MSDN.

Debug Symbols

When developers build an application in Visual Studio .NET 2003, they create two default configurations for the project: release and debug. One of the main differences between these two configuration modes is the way that debugging symbols are managed. In the debug configuration, a debugging symbols file program database is created, whereas for the release configuration, debugging information is not generated by default.

The program database file contains the information needed to map the compiled MSIL back to the source code; this allows debugging tools to fully report information such as variable names. In addition, the JIT compiler can generate tracking information at run time to map the native code back to the MSIL. Both tracking information and symbol files are needed to effectively debug managed code.

You should not distribute the symbol files with your application to the production environment, because this allows customers or other users to more easily reverse engineer your application (which is obviously a security concern). However, you should strongly consider changing the release configuration to ensure that it does generate debugging symbols. If you have not generated debugging symbols for the release version of your application, but you find that you need to debug it in the production environment, you need to rebuild the application, including debugging information, and redeploy the application to be able to debug it in the production environment. If you generate the debug symbols file with your release configuration, but keep them secured separately from the deployed application, you can install them into the production environment if (and only if) you need to debug the released application.

In Visual Studio .NET 2003, generation of the program database file and tracking information is controlled by the Generate debugging information option on the build page of the configuration section, in the project property pages of your projects. You can specify that the release configuration should generate the debugging symbols files by modifying the project property pages when the Release configuration is selected. If you compile your application with the command line, you can specify the /debug switch with various options to control the generation of debugging symbols and tracking information.

To help ease the management of symbols across your enterprise, you can use Microsoft Symbol Server to store your symbols in a centralized location and have the debuggers access them when they need them.

For more information about symbol management, see the following:

  • Bugslayer: Symbols and Crash Dumps

  • How to Get Symbols

  • INFO: Use the Microsoft Symbol Server to Acquire Debug Symbol Files

  • INFO: PDB and DBG Files - What They Are and How They Work

  • Production Debugging for .NET Framework Applications




Deploying. NET Applications Lifecycle Guide
Deploying .NET Applications: A Lifecycle Guide: A Lifecycle Guide (Patterns & Practices)
ISBN: B004V9MSJW
EAN: N/A
Year: 2003
Pages: 53

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net