To add the serviced components in your assembly to a COM+ application, you need to register that assembly with COM+. 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.
Signing Assembly and Assembly Location
To add an assembly to a COM+ application, the assembly must be signed (have a strong name) so the assembly resolver can map a client activation request to the corresponding assembly. Although in theory you need not install the assembly in the global assembly cache (GAC), in practice you should install it because the assembly DLL must be in a known location--either the system directory (for server applications that run in DllHost) or the hosting client process directory (if the client is not a COM+ server application). The other known location that the assembly resolver uses is the GAC. To maintain flexibility (to change from server to library application) and consistency, make sure you always install your serviced component assembly in the GAC.
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:
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:
Understanding Serviced Component Versions
Before exploring the three registration options, you need to understand the relationship between an assembly's version and COM+ components.
Every managed client of your assembly is built against the particular version of the assembly that contains your components, whether they are serviced or regular managed components. .NET zealously enforces version compatibility between the client's assembly and any other assembly it uses. The assembly's version is the product of its version number (major and minor numbers, such as 3.11) and the build and revision numbers. The version number is provided by the developer as an assembly attribute, and the build or revision numbers can be generated by the compiler--or the developer can provide them himself.
The semantics of the version and build or revision numbers tell .NET whether two particular assembly versions are compatible with each other, and which of the two assemblies is the latest. Assemblies are compatible if the version number is the same. The default is that different build and revision numbers do not indicate incompatibility, but a difference in either major or minor number indicates incompatibility. A client's manifest contains the version of each assembly it uses. At runtime, .NET loads for the client the latest compatible assemblies to use, and latest is defined using the build and revision numbers.
All this is fine while everything is under tight control of the .NET runtime. But how would .NET guarantee compatibility between the assembly's version and the configuration of the serviced components in the COM+ Catalog? The answer is via the COM+ component's ID.
The first time a serviced component is added to a COM+ application, the registration process generates a CLSID for it, based on a hash of the class definition and its assembly's version and strong name. Subsequent registration of the same assembly with an incompatible version is considered a new registration for that serviced component, and the component is given a new CLSID.
This way, the serviced component's CLSID serves as its configuration settings version number. Existing managed clients do not interfere with one another because each gets to use the assembly version it was compiled with. Each managed client also uses a particular set of configuration parameters for the serviced components, captured with a different CLSID. When a managed client creates a serviced component, the .NET runtime creates for it a component from an assembly with a compatible version and applies the COM+ configuration of the matching CLSID.
To register your component manually, use the RegSvcs.exe command-line utility. (In the future, Visual Studio.NET will probably allow you to invoke RegSvcs from the visual environment itself.) 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
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.
In any case, you must create that COM+ application in the Component Services Explorer beforehand; otherwise, the previous command line will fail. You can instruct RegSvcs to create the application for you using the
RegSvcs.exe /c MyApp MyAssembly.dll
Or if the name is specified in the assembly:
RegSvcs.exe /c MyAssembly.dll
When using the
/c switch, RegSvcs creates a COM+ application, names it accordingly, and adds the serviced components to it. If the Catalog already contains an application with that name, the registration fails.
You can also ask RegSvcs to try to find a COM+ application with that name and, if none is found, create one. This is done using the
RegSvcs.exe /fc MyApp MyAssembly.dll
Or if the name is specified in the assembly:
RegSvcs.exe /fc MyAssembly.dll
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.
By default, RegSvcs does not override the existing COM+ application (and its components) settings. If that assembly version is already registered with that COM+ application, then RegSvcs does nothing. If that version is not registered yet, it adds the new version and assigns new CLSIDs. Reconfiguring an existing version is done explicitly using the
RegSvcs.exe /reconfig /fc MyApp MyAssembly.dll
/reconfig switch causes RegSvcs to reapply any application, component, interface, and method attributes found in the assembly to the existing version and use the COM+ default settings for the rest, thus reversing any changes you made using the Component Services Explorer.
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
>. For example, when you add the serviced component in Example 10-1 to the COM+ Catalog, RegSvcs names it MyNamespace.MyComponent. 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 nonmanaged clients (COM clients). The default type library filename is <Assembly name>.tlb--the name of the assembly with a .tlb extension.
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 Administrator 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 Administrator 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.
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 void InstallAssembly(string assembly,
ref string application,
ref string tlb,
InstallationFlags installFlags );
The installation flags correspond to the various RegSvcs switches. See the MSDN Library for additional information on
RegistrationHelper. You can use
RegistrationHelper yourself as part of your installation program; for more information, see the section "Programming the COM+ Catalog" later in this chapter.
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:
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. Using application ID comes in handy when deploying the assembly in foreign markets--you can provide a command-line localized application name for every market while using the same application ID for your administration needs internally. The
ApplicationID attribute is defined in the
The Guid Attribute
Instead of having the registration process generate a CLSID for your serviced component, you can specify one for it using the
public class MyComponent :ServicedComponent,IMyInterface
Guid attribute is defined in the
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("My Serviced Component")]
public class MyComponent :ServicedComponent,IMyInterface
ProgId attribute is defined in the