Click here to Skip to main content
Click here to Skip to main content

Serviced Components in VB.NET

, 13 Apr 2003
Rate this:
Please Sign up or sign in to vote.
This article explains how to develop and deploy serviced components in Visual Basic .NET. It also explains about custom attributes which is used in COM+ services.

Introduction

.NET is Microsoft's next-generation component technology. It is designed from the ground up to simplify component development and deployment, as well as to support interoperability between programming languages. Despite its innovations and modern design, .NET is essentially a component technology. Like COM, .NET provides you with the means to rapidly build binary components, and Microsoft intends for .NET to eventually succeed COM. Like COM, .NET does not provide its own component services. Instead, .NET relies on COM+ to provide it with instance management, transactions, activity-based synchronization, granular role-based security, disconnected asynchronous queued components, and loosely coupled events. The .NET namespace that contains the types necessary to use COM+ services was named System.EnterpriseServices to reflect the pivotal role it plays in building .NET enterprise applications. A .NET component that uses COM+ services is called a serviced component to distinguish it from the standard managed components in .NET.

Developing serviced components

A .NET component that takes advantage of COM+ services needs to derive from the .NET base class ServicedComponent. ServicedComponent is defined in the System.EnterpriseServices namespace. To develop a simple serviced component following steps have to be followed:

  1. Define a class that derives directly or indirectly from the ServicedComponent class. For example, the following code ensures that the MyClass class is hosted by a COM+ application:
    Imports System.EnterpriseServices
        Public Class MyClass Inherits ServicedComponent
  2. Apply service attributes to the assembly, class, or method.
    Imports System.EnterpriseServices
    
    <Transaction(TransactionOption.Required)> _
    Public Class MyClass Inherits ServicedComponent
    
        <AutoComplete()> 
        Public Sub DoSomething()
    
        End Sub
    
    End Class
  3. Deploy the serviced component application by registering its assemblies dynamically or manually.

After a serviced component is registered, clients can create instances of the component the way they create instances of any other component.

There are two ways to configure a serviced component to use COM+ services. The first is COM-like: you derive from ServicedComponent, add the component to a COM+ application, and configure it there. The second way is to apply special attributes to the component, configuring it at the source-code level. When the component is added to a COM+ application, it is configured according to the values of those attributes. Attributes are discussed in greater detail below.

.NET allows you to apply attributes to your serviced components with great flexibility. If you do not apply your own attributes, a serviced component is configured using default COM+ settings when it is added to a COM+ application. You can apply as many attributes as you like. A few COM+ services can only be configured via the Component Services Explorer. These services are mostly deployment-specific configurations, such as persistent subscriptions to COM+ events and allocation of users to roles. In general, almost everything you can do with the Component Services Explorer can be done with attributes. It is recommended that you put as many design-level attributes as possible (such as transaction support or synchronization) in the code and use the Component Services Explorer to configure deployment-specific details.

Registering serviced components

A serviced component is hosted by a COM+ application and must be accessible to that application. For accessibility, serviced components have the following registration and configuration requirements:

  • Assembly must be strong-named.
  • Assembly must be registered in the Windows registry.
  • Type library definitions must be registered and installed into a specific COM+ application.
  • Services added programmatically must be configured in the COM+ catalog.

You can perform that registration in three ways:

  • Manually, using a command line utility called RegSvcs.exe.
  • Dynamically, by having the client program register your assembly automatically.
  • Programmatically, by writing code that does the registration for you using a utility class provided by .NET.

Regardless of the technique you use, the registration process adds your serviced components to a COM+ application and configures them according to the default COM+ settings or according to their attributes (if present in the code). If the assembly contains incompatible attributes, the incompatibility is detected during registration and the registration is aborted. Future versions of the .NET compilers may detect incompatibilities during compilation time.

Manual registration

To register your component manually, use the RegSvcs.exe command-line utility. RegSvcs accepts as a parameter, the name of the file containing your assembly's metadata. In a single DLL assembly, that file is simply the assembly file. If you do not specify as an assembly attribute the name of the COM+ application that should host your components, RegSvcs must be told that name explicitly as a command-line parameter, using the /appname: switch.

For example, if your single DLL assembly resides in MyAssembly.dll and you wish to add the serviced components in that assembly to the MyApp COM+ application, you would use RegSvcs in this manner:

RegSvcs.exe /appname: MyApp  MyAssembly.dll

The command-line application name is ignored if the assembly contains an application name.

If you don't specify a COM+ application name, either in the assembly or as a command-line parameter, RegSvcs uses the assembly name for the application name. If your assembly is called MyAssembly, RegSvcs adds the components to the MyAssembly COM+ application. This behavior is the same for all the command-line switches.

When RegSvcs adds a serviced component to the COM+ Catalog, it must give it a class-ID (CLSID) and a prog-ID. RegSvcs creates a GUID for every component (based on the assembly's version and the class definition) and names it < Namespace>.<Component name>. You can also specify the CLSID and the prog-ID of your serviced components using attributes.

In addition to adding the serviced components in the assembly to a COM+ application, RegSvcs creates a type library. This library contains interface and CoClass definitions to be used by unmanaged clients (COM clients). The default type library filename is <Assembly name>.tlb--the name of the assembly with a .tlb extension.

Dynamic registration

When a managed client creates a serviced component, the .NET runtime resolves which assembly version to use for that client. Next, the runtime verifies that the required version is registered with COM+. If it is not registered, the runtime installs it automatically. This process is called dynamic registration. As with RegSvcs, if the assembly contains an application name, then that name is used; if it does not, then the assembly's name is used for the COM+ application's name.

Note that only .NET clients can rely on having dynamic registration done when they instantiate a .NET serviced component. For COM clients, you must use the RegSvcs utility. Another limitation of dynamic registration is that serviced components in the assembly are configured according to the attributes in the assembly and the COM+ defaults. If you require configuring some services (such as events subscriptions) using the Component Services Explorer for your application to function properly, you must use RegSvcs to register your components and provide the additional configuration using the Component Services Explorer. Only then can clients use your serviced components. As a result, dynamic registration is only useful for serviced components that contain all the service configurations they need in their code through the use of attributes. Finally, dynamic registration requires that the user invoking the call that triggers dynamic registration be a member of the Windows 2000 Administrators group. It has this requirement because dynamic registration makes changes to the COM+ Catalog; if the user invoking it is not a member of the Windows 2000 Administrators group, dynamic registration will fail.

In general, you should use RegSvcs and the Component Services Explorer rather than relying on dynamic registration. If you want to rely on dynamic registration of your serviced components, you should increment the version number of your assembly every time you make a change to one of the components' attributes, to ensure that you trigger dynamic registration.

Programmatic registration

Both RegSvcs and dynamic registration use a .NET class called RegistrationHelper to perform the registration. RegistrationHelper implements the IRegistrationHelper interface, whose methods are used to register and unregister assemblies. For example, the InstallAssembly( ) method registers the specified assembly in the specified COM+ application (or the application specified in the assembly). This method is defined as:

Public Sub InstallAssembly( _
   ByVal assembly As String, _
   ByRef application As String, _
   ByRef tlb As String, _
   ByVal installFlags As InstallationFlags _
    )

The installation flags correspond to the various RegSvcs switches. See the MSDN Library for additional information on RegistrationHelper.

Configuring serviced components

Specifying application name

You can provide .NET with an assembly attribute, specifying the name of the COM+ application you would like your components to be part of, by using the ApplicationName assembly attribute:

<Assembly: ApplicationName("MyApplication")>

If you do not provide an application name, .NET uses the assembly name. The ApplicationName attribute (and the rest of the serviced components attributes) is defined in the System.EnterpriseServices namespace. You must add this namespace to your project references and reference that namespace in your assembly information file:

imports System.EnterpriseServices;

The ApplicationID attribute

Every COM+ application has a GUID identifying it called the application ID. You can provide an assembly attribute specifying the application ID in addition to the application name:

<Assembly: ApplicationID("8BE192FA-57D0-49a0-8608-6829A314EEBE")>

Unlike the application name, the application ID is guaranteed to be unique, and you can use it alongside the application name. Once an application ID is specified, all searches for the application during registration are done using the application ID only, and the application name is only useful as a human-readable form of the application identity.

The Guid attribute

Instead of having the registration process generate a CLSID for your serviced component, you can specify one for it using the Guid attribute:

imports System.EnterpriseServices; 
<Guid ("260C9CC7-3B15-4155-BF9A-12CB4174A36E")> Public Class MyCls
     Inherits ServicedComponent
    'Code Here
End Class

The Guid attribute is defined in the System.Runtime.InteropServices namespace.

When you specify a class ID, subsequent registrations of the assembly don't generate a new CLSID for the component, regardless of the version of the assembly being registered. Registrations always reconfigure the same component in the COM+ Catalog. Specifying a class ID is useful during development, when you have multiple cycles of code-test-fix. Without it, every invocation by the test client triggers a dynamic registration--you very quickly clutter the COM+ application with dozens of components, when you actually only use the latest one.

The ProgId attribute

Instead of having the registration process generate a name for your serviced component (namespace plus component name), you can specify one for it using the ProgID attribute:

imports System.EnterpriseServices; 
<ProgId("MyClass.Web")> Public Class MyCls
     Inherits ServicedComponent
    'Code Here
End Class

The ProgId attribute is defined in the System.Runtime.InteropServices namespace.

Application activation type

To specify the COM+ application's activation type, you can use the ApplicationActivation assembly attributes. You can request that the application be a library or a server application:

<assembly: ApplicationActivation(ActivationOption.Server)>
or:
<assembly: ApplicationActivation(ActivationOption.Library)>

If you do not provide the ApplicationActivation attribute, then .NET uses a library activation type by default. Note that this use differs from the COM+ default of creating a new application as a server application

The Description attribute

The Description attribute allows you to add text to the description field on the General Properties tab of an application, component, interface, or method. After registration, the assembly-level description string becomes the content of the hosting COM+ application's description field; the class description string becomes the content of the COM+ component description field. The interface and method descriptions are mapped to the corresponding interface and method in the Component Services Explorer.

COM+ object pooling

The ObjectPooling attribute is used to configure every aspect of your component's object pooling. The ObjectPooling attribute enables or disables object pooling and sets the minimum or maximum pool size and object creation timeout. For example, to enable object pooling of your component's objects with a minimum pool size of 3, a maximum pool size of 10, and a creation timeout of 20 milliseconds, you would write:

<ObjectPooling(MinPoolSize=3,MaxPoolSize=10,CreationTimeout=20)>
Public Class MyClass
    Inherits ServicedComponent
        'Code Here
End Class

The MinPoolSize, MaxPoolSize, and CreationTimeout properties are public properties of the ObjectPooling attribute class. If you do not specify values for these properties (all or just a subset) when your component is registered, the default COM+ values are used for these properties (a minimum pool size of 0, a maximum pool size of 1,048,576, and a creation timeout of 60 seconds).

COM+ constructor string

Any COM+ configured component that implements the IObjectConstruct interface has access during construction to a construction string, configured in the Component Services Explorer. Serviced components are no different. The base class, ServicedComponent, already implements the IObjectConstruct interface as a virtual method (it has only one method). Your derived serviced component can override the Construct( ) method, as shown in this code sample:

Public Class Web
Inherits ServicedComponent
Protected Overrides Sub Construct( _
             ByVal constructString As String)
      If Not constructString Is Nothing Then
            mstrConstructionString = constructString
      End If
End Class

The MinPoolSize, MaxPoolSize, and CreationTimeout properties are public properties of the ObjectPooling attribute class. If you do not specify values for these properties (all or just a subset) when your component is registered, the default COM+ values are used for these properties (a minimum pool size of 0, a maximum pool size of 1,048,576, and a creation timeout of 60 seconds).

If the checkbox "Enable object construction" on the component activation tab is selected, then the Construct( ) method is called after the component's constructor, providing it with the configured construction string.

You can also enable construction string support and provide a default construction string using the ConstructionEnabled attribute:

<ConstructionEnabled(Enabled=true, Default = "My String")>
Public Class Web
Inherits ServicedComponent
End Class

The ConstructionEnabled attribute has two public properties. Enabled enables construction string support for your serviced component in the Component Services Explorer (once the component is registered) and Default provides an initial string value. When your component is registered with COM+, the registration process assigns the default string to the constructor string field on the component activation tab. The default string has no further use after registration. New instances of your component receive as a constructor string, the current value of the constructor string field. For example, if the default string is String A, when the serviced component is registered, the value of the constructor string field is set to String A. If you set it to a different value, such as String B, new instances of the component get String B as their construction string. They receive the current value, not the default value.

COM+ transactions

You can configure your serviced component to use the five available COM+ transaction support options by using the Transaction attribute. The Transaction attribute's constructor accepts an enum parameter of type TransactionOption, which has following five values

  • Disabled
  • NotSupported
  • Supported
  • Required
  • RequiresNew

For example, to configure your serviced component to require a transaction, use the TransactionOption.Required value:

<Transaction(TransactionOption.Required)>
Public Class Web
    Inherits ServicedComponent 
End Class

Strong named assemblies

A strong name consists of the assembly's identity---it's simple text name, version number, and culture information (if provided)---plus a public key and a digital signature. It is generated from an assembly file (the file that contains the assembly manifest, which in turn contains the names and hashes of all of the files that make up the assembly), using the corresponding private key. Once an assembly is created, you cannot sign it with a strong name. To create a strong-named assembly, you must sign it with a strong name when you create it.

For creating a strong named assembly, you need to create a cryptographic key pair using the Strong Name tool (Sn.exe) and assign that key pair to the assembly using either a command-line compiler or the Assembly Generation tool (Al.exe). The .NET Framework SDK provides both Sn.exe and Al.exe.

To create a key pair

At the command prompt, type the following command:

sn –k <file name>

In this command, file name is the name of the output file containing the key pair. The following example creates a key pair called sgKey.snk.

sn -k sgKey.snk

Signing an assembly with a strong name

There are two ways to sign an assembly with a strong name:

  • Use the Assembly Generation tool (Al.exe) provided by the .NET Framework SDK.
  • Use assembly attributes to insert the strong name information in your code. You can use either the AssemblyKeyFile attribute or the AssemblyKeyName attribute, depending on where the key file to be used is located.

To create and sign an assembly with a strong name using the Assembly Generation tool

At the command prompt, type the following command:

al /out:<assembly name> <module name> /keyfile:<file name>

In this command, assembly name is the name of the assembly to sign with a strong name, module name is the name of the code module used to create the assembly, and file name is the name of the container or file that contains the key pair.

The following example signs the assembly MyAssembly.dll with a strong name using the key file sgKey.snk.

al /out:MyAssembly.dll MyModule.netmodule /keyfile:sgKey.snk

To sign an assembly with a strong name using attributes

In a code module, add the AssemblyKeyFile attribute or AssemblyKeyName attribute specifying the name of the file or container that contains the key pair to use to sign the assembly with a strong name. The following code example uses the AssemblyKeyFile attribute with a key file called sgKey.snk.

<Assembly:AssemblyKeyFile ("sgKey.snk")>

Installing an assembly into the Global Assembly Cache

When an assembly that uses ApplicationActivationOption is set to server, the assembly is loaded by dllhost.exe, which most likely is not in the same directory as the client. Assemblies that use serviced components in COM+ server apps should be placed in the GAC. Assemblies that use serviced components in COM+ libraries apps may not need to be placed in the GAC (unless they are located in different directories). The only exception is when hosting with ASP.NET—assemblies should not be placed in the GAC to enable shadow copy to operate correctly. So it is better to place all serviced components inside the GAC.

There are two ways to install an assembly into the Global Assembly Cache:

  • Using the Windows Installer 2.0.

    This is the recommended and most common way to add assemblies to the Global Assembly Cache. The installer provides reference counting of assemblies in the Global Assembly Cache and other benefits.

  • Using the Global Assembly Cache tool (Gacutil.exe).

    You can use Gacutil.exe to add strong-named assemblies to the Global Assembly Cache. This tool can also be used to view the contents of the Global Assembly Cache.

To install a strong-named assembly into the Global Assembly Cache

At the command prompt, type the following command:

gacutil –i <assembly name>

In this command, assembly name is the name of the assembly to install in the Global Assembly Cache. The following example installs an assembly with the file name hello.dll into the Global Assembly Cache.

gacutil -i hello.dll

Conclusion

This article explains how to develop and deploy serviced components in Visual Basic .NET. It also explains about custom attributes which is used in COM+ services.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Saravanak

India India
No Biography provided

Comments and Discussions

 
GeneralCOM+ serviced component Pinmembermailmechandru19-Aug-05 22:44 
GeneralArticle is almost all plagiarized! Pinmemberejohnson054715-Dec-04 6:29 
GeneralRe: Article is almost all plagiarized! Pinmemberbeertroll7-Sep-06 10:21 
GeneralQueued componet dynamic registration PinsussAnonymous3-Oct-04 2:14 
Hi !!!
 
I have a queued comonent that needs to be dynamically registered . Is is possible ? Also i needed my queued copnenet to start as soon as a user requests it .Should i be using the comadmincatlog class to start my queued
componet ?? any help is appreciated !!
 
P.S - Nice article
GeneralRe: Queued componet dynamic registration PinmemberSaravana793-Oct-04 19:06 
GeneralRemote Server PinmemberClassGenerator3-Dec-03 6:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 14 Apr 2003
Article Copyright 2003 by Saravanak
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid