asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Deploying Serviced Components
By Thiru Thangarathinam
Rating: 4.5 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    In this Internet world of connected network applications, it is reasonable to expect that your Web applications scale to meet the needs of millions of users who will access your Web site. COM+ is a core element in the Windows DNA 2000 methodology to create scalable, extensible, and maintainable distributed applications. However, in the .NET world, COM+ components are referred to as serviced components. Due to the number of changes in the .NET strategy, the deployment model for serviced components is different from deploying traditional COM+ components. In this article, we will understand how to deploy serviced components using the various tools provided by the .NET Framework. Along the way, we will also highlight how the deployment model varies for different types of serviced components. Finally, we will wrap it up by understanding how the deployment of serviced components can be automated using a Windows installer project.

    Component services in Windows 2000 has a wealth of enterprise functionality that provides all the plumbing required for creating distributed, Web-enabled applications. Although COM+ services were originally designed for use with COM components, it would be nice if .NET components could also use them because of services such as object pooling, database connection pooling, sharing resources, role based security, and distributed transaction processing monitoring that COM+ runtime provides.

    In the .NET Framework, there is a separate namespace called System.EnterpriseServices that contains all the classes required for providing COM+ services to applications. For an introduction to COM+, please take a look at the following link from TechNet. Introduction to COM and COM+.

    Before looking at the different ways of deploying serviced components, let us examine the ServicedComponent class, one of the most important classes present in the System.EnterpriseServices namespace.

    ServicedComponent

    To be able to create .NET objects that make use of COM+ services, we need to derive our objects from System.EnterpriseServices.ServicedComponent class, which provides methods for our objects to seamlessly interact with COM+ runtime, thereby allowing us to take advantage of the COM+ services. Before we look at deploying serviced components, we need to understand the difference between server applications and library applications. Basically, a COM+ library application is one that runs in the process of the client that creates it, whereas a COM+ server application runs in the process space of the COM+ executable (dllhost.exe).

    Different Ways of Deploying Serviced Components

    When you compile a COM component, it creates a type library, which provides COM+ with all the information required for installing the component into COM+. But .NET components, when compiled, emit an assembly (contains manifest, MSIL, meta-data, etc) that is completely different from the type library. So we need to create a type library from the assembly that makes it possible for the assembly to be seamlessly installed into COM+.

    There are three ways of deploying a .NET component in component services Windows 2000:

    • Using the Regsvcs command line utility
      This command line utility takes the name of the assembly as the input, creates a type library by reading the assembly, and finally registers the object with COM+.
    • Using the automatic registration mechanism provided by the .NET Framework
      At runtime, the CLR (Common Language Runtime) automatically creates a type library based on the assembly and COM+ uses the information present in the type library to install the objects. This is called lazy registration and this method works only for library applications.
    • Using the RegistrationHelper class that is part of the System.EnterpriseServices namespace.
      The InstallAssembly method of the RegistrationHelper class can be used to programmatically register .NET objects with COM+.

    In addition to deploying an assembly in COM+, we also have to deploy it in any one of the following locations:

    • Private bin directory of the client application. This is the default location the assembly is deployed to, if a client uses the Add Reference dialog box to reference the serviced component assembly.
    • Shared location (GAC) - Makes the assembly available to all the clients on a machine

    When looking at deploying serviced components within a library application, we will consider the first method of deployment (private deployment), and when we look at server applications, we will see how to use GAC for deploying the serviced components in a shared location.

    Before we use a serviced component, we need a key file to strongly sign the assembly. To generate a key file, we must first run the sn.exe (Strong Name utility) with the -k switch. As a result, this will create a file containing the public/private key pair. Then we can sign the assembly with the key pair, adding the following line in the Assemblyinfo.cs file <assembly: AssemblyKeyFile("..\\..\\LibraryApp.snk")>.

    We will start off by looking at how to deploy a serviced component within a COM+ library application.

    Deploying a serviced component within a library application

    First, we will create a new project by selecting File->New Project from Visual Studio.NET. In the new project dialog box, we will select Visual C# class library as the project type and enter the name of the project as LibraryApp as shown below.

    Once the project is created, we will rename default class (Class1) to SampleLibrary and modify it to look like the following. We derive the class from ServicedComponent class to take advantage of the services provided by COM+.

     

    public class SampleLibrary : ServicedComponent

    {

           public SampleLibrary()

           {

           }

     

           public string WriteMessage()

           {

                  return "This message is from a library application";

           }

    }

    As you can see from the above, we have a very simple method named WriteMessage that returns a string as its return value.

    Then we will create a key file using the sn utility. To generate the key file, we will run the Visual Studio .NET command prompt and then enter the following command as shown below.

    Once the file is generated, we will add the key file to the project. We then add the following lines to the AssemblyInfo.cs file.

    [assembly: AssemblyKeyFile("..\\..\\LibraryApp.snk")]

    [assembly: ApplicationName("LibraryApp")]

    [assembly: ApplicationActivation(ActivationOption.Library)]

    [assembly: Description("This is a library application")]

    In the above lines of code:

    • ApplicationName - Specifies the name that is used for creating the COM+ application
    • ApplicationActivation - Allows us to specify how the serviced component is activated - in-process or out-of-process. In this case, we have indicated that we want the serviced component to be activated in the client's process space by specifying the value ActivationOption.Library.
    • Description - Specifies a description for the assembly

    After we compile the serviced component, we then need to deploy the assembly in COM+. We can do this by running the services installation utility, regsvcs.exe, from the command line, as shown here:

    regsvcs LibraryApp.dll
    

    When you execute the command line utility, it basically performs the following actions.

    • First, it registers the CLR assembly as a COM component (as if you had run the Assembly Registration Utility, regasm.exe).
    • Second, it emits a COM type library (as if you had run the Assembly to Type Library Converter, tlbexp.exe) and uses it to deploy the configured classes (that are present in the assembly) in the COM+ catalog.
    • Then it creates the target application described in the assembly's ApplicationName and ApplicationActivation attributes by default.
    • Finally, it uses the .NET Reflection APIs to interrogate the meta-data for the configured classes in the assembly and uses that information to programmatically update the COM+ catalog so that each class will have the appropriate declarative attribute settings. If a configured class does not have a particular declarative attribute, regsvcs.exe will use a default value instead.

    After we run the regsvcs utility, we can verify that the component is properly installed in COM+ by bringing up the Component Services Explorer.

    As you can see from the above screenshot, we have a new library application named LibraryApp (as specified in the AssemblyInfo.cs file) and inside the library application we also have the LibraryApp component installed. To test our serviced component, we will write a simple Visual C# Windows application and invoke its methods.

    Client application for the serviced component

    We will name the client application as LibraryAppClient and add a command button to the default form Form1.cs. Then we add reference to the LibraryApp assembly by using the Add Reference option.

    At the top of the file, we also add the following statement to import the namespace reference.

    using LibraryApp;

    In the click event of the command button, we will write the following lines of code.

    private void btnInvoke_Click(object sender, System.EventArgs e)

    {

           SampleLibrary obj = new SampleLibrary();

           MessageBox.Show(obj.WriteMessage());

    }

    Now if you execute the application and click on the command button, you will see the message from the serviced component being displayed.

    Now that we understand how to deploy a serviced component in a library application in COM+, let us address the steps involved in deploying the serviced component as part of a server application.

    Deploying serviced components within a server application

    As we mentioned before, serviced components hosted within a server application are always activated in the address space of the COM+ executable dllhost.exe. In addition to that, serviced components (deployed within a COM+ server application) should be deployed in the GAC. This is done to allow the COM+ to load the assembly independent of the directory in which the actual client is running. For this example, we will create a new Visual C# Class Library application named ServerApp as shown below.

    After the project is created, we will rename the default class to SampleServer and add the following lines of code.

    public class SampleServer : ServicedComponent

    {

           public SampleServer()

           {

     

           }

           public string WriteMessage()

           {

                  return "This message is from a server application";

           }

    }

    As similar to previous example, we also create a key file named ServerApp.snk and add it to the project. Then we add the following to the AssemblyInfo.cs file.

    
    [assembly: ApplicationName("ServerApp")]
    [assembly: Description("This is a server application")]
    [assembly: ApplicationActivation(ActivationOption.Server)]
    [assembly: AssemblyKeyFile("..\\..\\ServerApp.snk")]
    
    
    As Once the file you can see from the above, we specify that we want this assembly to be activated in the COM+ executable process space by setting the ApplicationActivation attribute to ActivationOption.Server. Now that we have specified all of the options, we can go ahead and compile the component to generate the assembly. Once the assembly is generated, we will install the assembly into GAC by using the utility named gacutil.exe. To install the assembly, we pass in the name of the assembly as well as the command switch i as arguments to gacutil utility.
    gacutil -i ServerApp.dll
    

    Once the assembly is installed in GAC, we can then register the component within COM+ by executing the regsvcs utility.

    regsvcs ServerApp.dll
    
    Now that we have deployed the assembly, we can write a client application and test the methods of the classes present in the deployed assembly.

    Client application for the serviced component

    We will start off by creating a new Visual C# Windows application named ServerAppClient and add the following lines of code to the Form1.cs file.

    using ServerApp;

     

    private void cmdServerApp_Click(object sender, System.EventArgs e)

    {

           SampleServer obj = new SampleServer();

           MessageBox.Show(obj.WriteMessage());

    }

    If you execute the application and click on the command button, you will see the message that was returned by the serviced component.

    Automating Deployment Using the System.EnterpriseServices.RegistrationHelper Class

    The manual deployment methods described above work well only for small-sized applications. If you are using serviced components in an enterprise application that typically requires a complex installation setup program (for installing the application on the target servers), then you need to deploy the serviced components as part of the set up program. As part of the installation program, you may also need to install the assembly in the GAC. Even though it is possible to create scripts and batch files to accomplish such an installation, there is a much easier way. Using Visual Studio .NET Setup & Deployment projects, we can easily create a setup project that includes the ability to call your own code to register components or take any other action we need to at installation time and also at uninstall time. To accomplish this, we need to create a custom action that is executed during the install and uninstall stages. To create a custom action, all you need to do is to create a class as a part of the assembly that inherits from System.Configuration.Install.Installer and then add a custom install action to your deployment project. For this example, we will consider the LibraryApp serviced component that we created previously.

    To add an installer class to the LibraryApp serviced component assembly:

    • Right click on LibraryApp project
    • Select Add / New Item... this will display the Add New Item dialog
    • In the Categories pane select Code
    • In the Templates pane select Installer Class and name the class as CustomActionInstaller.
    Once the class is created, we will add Install and Uninstall methods to it.
    
    public override void Install(System.Collections.IDictionary stateSaver)
    {
    	try 
    	{
    		string appID = null;
    		string typeLib = null;
    		// Get the location of the current assembly
    		string assembly = GetType().Assembly.Location;
    		// Install the application
    		RegistrationHelper regHelper = new RegistrationHelper ();
    		regHelper.InstallAssembly (assembly, ref appID, ref typeLib,
    		InstallationFlags.FindOrCreateTargetApplication);
    		// Save the state - you will need this for the uninstall
    		stateSaver.Add ("AppID", appID);
    		stateSaver.Add ("Assembly", assembly);
    	}
    	catch(Exception ex)
    	{
    #if DEBUG
    			Debug.WriteLine (ex);
    #endif
    		StreamWriter writer = File.AppendText ("InstallError.log");
    		writer.WriteLine ("Uninstall Error: {0}", ex.Message);
    		// If the installer catches the exception it will display 
    		// an error message.  Show a friendly error message
    		throw new ApplicationException
    		(
    			"Error installing the middle tier", ex);
    		}
    	} 
    
    	
    public override void Uninstall( System.Collections.IDictionary savedState)
    {
    try
    	{
    		// Get the state created when the app was installed
    		string appID = (string)savedState["AppID"];
    		string assembly = (string)savedState["Assembly"];
    		// Uninstall the application
    		RegistrationHelper regHelper = new RegistrationHelper ();
    		regHelper.UninstallAssembly (assembly, appID);
    	}
    	catch ( Exception ex)
    	{
    		// Don't allow unhandled exceptions during uninstall
    #if DEBUG
    			Debug.WriteLine (ex);
    #endif
    		StreamWriter sw = File.AppendText ("InstallError.log");
    		sw.WriteLine ("Uninstall Error: {0}", ex.Message);
    		}
    	}
    
    
    Let us walk through the above lines of code. We start by getting the reference to the location of the current assembly.
    
    		string assembly = GetType().Assembly.Location;
    
    
    Here we create an instance of the RegistrationHelper class.
    
    		RegistrationHelper regHelper = new RegistrationHelper ();
    
    
    After that, we install the assembly by invoking the InstallAssembly method, passing in the appID and typeLib variables as byref arguments. After the assembly is installed, we get reference to the newly created application id as well as the type library in the local variables.
    
    		regHelper.InstallAssembly (assembly, ref appID, ref typeLib,
    		InstallationFlags.FindOrCreateTargetApplication);
    
    
    We then save the AppID and the assembly location in the supplied collection object for later retrieval. The persisted information is used during the uninstall phase of the application.
    
    		stateSaver.Add ("AppID", appID);
    		stateSaver.Add ("Assembly", assembly);
    }
    
    
    If there is any exception during the execution of above lines of code, we then catch the exception and write that information to a log file called InstallError.log.
    
    	catch(Exception ex)
    	{
    #if DEBUG
    			Debug.WriteLine (ex);
    #endif
    		StreamWriter writer = File.AppendText ("InstallError.log");
    		writer.WriteLine ("Uninstall Error: {0}", ex.Message);
    		// If the installer catches the exception it will display 
    		// an error message.  Show a friendly error message
    		throw new ApplicationException
    		(
    			"Error installing the middle tier", ex);
    		}
    	} 
    
    
    In the Uninstall method, we start by getting the AppID and assembly information from the collection object.
    
    		// Get the state created when the app was installed
    		string appID = (string)savedState["AppID"];
    		string assembly = (string)savedState["Assembly"];
    
    
    We then uninstall the assembly by invoking the UninstallAssembly method of the RegistrationHelper class.
    
    		RegistrationHelper regHelper = new RegistrationHelper ();
    		regHelper.UninstallAssembly (assembly, appID);
    	}
    
    
    Here again, in the exception block, we write the exception information to an external log file named InstallError.log.
    
    	catch ( Exception ex)
    	{
    		// Don't allow unhandled exceptions during uninstall
    #if DEBUG
    			Debug.WriteLine (ex);
    #endif
    		StreamWriter sw = File.AppendText ("InstallError.log");
    		sw.WriteLine ("Uninstall Error: {0}", ex.Message);
    		}
    	}
    
    
    Once we have created the installer class, we can then add a custom action to the deployment project so that it automatically invokes the Install and Uninstall methods of CustomInstaller class. Before that, we will need to add a new deployment project to our existing LibraryApp solution. For this reason, we will create a new project named LibraryAppSetup as shown below.

    Next we need to add the output of the LibraryApp project to the deployment project. To accomplish this, we right click on the LibraryAppSetup project and select Add->Project Output. In the Add Project Output Group dialog box, select LibraryApp in the project drop down box and select Primary Output in the list of possible options. Next in order for the installer to invoke the Install and Uninstall methods of the CustomActionInstaller class, we need to add a custom action to our deployment project.

    Adding Custom Actions

    Custom actions will be invoked during different phases of the installation. The Commit and Rollback phases occur after the installation finishes or is rolled back. You should not attempt to do any significant work during these phases. The install method will be called during the install phase and the uninstall method during the uninstall phase.

    To add a custom action:

    • Right click on LibraryAppSetup project and select View->Custom Actions
    • Right click on the Install phase and select Add Custom Action...
    • Navigate through the target machine file system to locate the LibraryApp assembly that contains the custom action class.

    Deploying the assembly in GAC

    As part of the installation, it is also possible to deploy the serviced component within GAC. This is very useful, if you are trying to deploy a serviced component within a COM+ server application. To install the serviced component in GAC, you need to perform the following.

    • Right click on the LibraryAppSetup project and select View->File System.
    • By default, you will not see Global assembly cache folder in the list of folders. To add global assembly cache folder to the list, right click on File System on Target Machine and select Add Special Folder->Global Assembly Folder.
    • Right click on the global assembly folder and select Add->Assembly option to add the assembly to the GAC folder.

    Now if you build the installer and run the LibraryAppSetup.msi file, you will see that the assembly is not only registered with component services, but also deployed within the GAC.

    XCOPY Deployment and Serviced Components

    One of the goals of the .NET Framework is to simplify the installation of systems by supporting XCOPY deployment. The term XCOPY refers to an MS-DOS command-line utility for copying files and directories from one location to another. The purpose of XCOPY deployment is to make it possible to install applications on remote servers without executing any code there. To support XCOPY deployment, the CLR/COM+ integration plumbing allows you to ignore the execution of regsvcs.exe at installation time and takes care of registration the first time the serviced component is used. This is called lazy registration, and it can be useful for deploying serviced components within a library application. However, there are some shortcomings to the XCOPY deployment that we should be aware of.

    • First, the COM+ catalog can only be updated by the users included in the Administrators role defined by the COM+ System application. By default, only local administrators are included in that role. As a result, in order to successfully register the serviced component, the code that first uses your serviced component has to have administrative privileges. If it does not, registration will fail.
    • The second shortcoming is that if you want to deploy a serviced component in GAC, you can do that easily by copying the file to the appropriate directory. However, if you want to deploy the assembly within a sever application as well, then there is probably additional work to do. Specifically, you need to set the COM+ server application's security principal, which cannot be done automatically using meta-data. If you are deploying your configured classes in a COM+ library application, this becomes a non-issue as long as your assembly is deployed in a place where the clients can find it.

    When do you install the serviced component in GAC?

    You will need to install the serviced component in GAC, when any one of the following conditions is true:

    • Any application using SOAP (both client and server) or .NET Remoting
    • If you are accessing the serviced component from managed code and the assembly is not in the same directory as the executable. In short, if you want to find an assembly from a managed activation, it is necessary to be in the GAC unless it is in your application directory.
    • You want all the client applications within that machine to share the same assembly.
    • Serviced components placed in a COM+ server application should be placed in the GAC. Serviced components placed in a COM+ library application may not need to be placed in the GAC (unless they are located in different directories). requires that the current logged-on user be a member of the administrators group.

    Conclusion

    In this article, we have discussed how to deploy serviced components using the various classes and tools supplied by the .NET Framework. We have also seen how easy it is to use the Windows installer technology to create a Windows installer project to automate the deployment of serviced components.

    I hope you find this article useful and thanks for reading.

    About the Author

    Thiru has almost six years of experience in architecting, designing, developing and implementing applications using Object Oriented Application development methodologies. He also possesses a thorough understanding of software life cycle (design, development and testing).

    He is an expert with ASP.NET, .NET Framework, Visual C#.NET, Visual Basic.NET, ADO.NET, XML Web Services and .NET Remoting and holds MCAD for .NET, MCSD and MCP certifications.

    Thiru has authored numerous books and articles. He can be reached at thiruthangarathinam@yahoo.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Feb 23, 2005 - My Feature in Visual Basic 2005
    In this article, Thiru Thangarathinam demonstrates the different classes and features available through the My namespace. By providing a speed-dial that allows you to more quickly and effectively utilize .NET framework functionalities in your application, the My feature provides huge productivity improvements for .NET developers.
    [Read This Article]  [Top]
    Oct 6, 2004 - Creating Triggers Using Managed Code in SQL Server 2005
    Thiru Thangarathinam discusses taking advantage of the integation between the .NET CLR and SQL Server 2005 in order to do things like create triggers using managed code.
    [Read This Article]  [Top]
    Sep 8, 2004 - Custom Object Data Binding with .NET
    Developers often use brute force coding to marshal data between the GUI and application objects. In this article, Luther Stanton explains how to use .NET's out-of-the box data-binding functionality to make this job much easier.
    [Read This Article]  [Top]
    Aug 17, 2004 - The Perfect Service - Part 2
    Ambrose Little provides the complete source code for his 'Perfect Service' and explains how the .NET Service Manager enables features such as drag-n-drop deployment.
    [Read This Article]  [Top]
    Aug 12, 2004 - Middle-Tier Hosting: Enterprise Services, IIS, DCOM, Web Services, and Remoting
    There is broad-reaching debate about remoting, Web services, Enterprise Services, and DCOM. In short, it is a debate about the best technology to use when implementing client/server communication in .NET. Rocky Lhotka shares his thoughts on the issue while offering clear explanations of basic application architecture terminology.
    [Read This Article]  [Top]
    Jul 21, 2004 - COM Interop Exposed
    This article provides and excellent foundation for COM Interop. It reviews COM's background, explains how VB6 interacts with COM, and then shows how to design .NET components to smoothly interact with COM.
    [Read This Article]  [Top]
    Jun 24, 2004 - The Perfect Service - Part 1
    The first article in this two-part series shows how to get Ambrose Little's .NET Service Manager running and then how to add plug-n-play services to it using drag-n-drop or XCOPY.
    [Read This Article]  [Top]
    May 25, 2004 - Generics In-Depth
    Although generics are extremely useful, they also seem to have a certain mystique that cannot be readily explained. This article hopes to remove that aura of mystery by showing just how easy it is to use generics and how useful they can be in many common situations.
    [Read This Article]  [Top]
    May 11, 2004 - SharePoint Security and .NET Impersonation
    When implementing custom components that require access to restricted resources, implicit impersonation must be used. Jay Nathan shows how to create a class that makes using .NET Impersonation a snap.
    [Read This Article]  [Top]
    Mar 23, 2004 - Exploiting .NET's Advanced Deployment Features
    Tony Arslan shows how to use VS .NET's custom deployment feature to create configuration files on the target machine during installation.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers