Converting Assemblies to COM Type Libraries

PC Repair Tools

Advanced Registry Cleaner PC Diagnosis and Repair

Get Instant Access

The .NET SDK comes with two tools that can be used to generate type libraries from assemblies: the Type Library Exporter (tlbexp.exe) and the Assembly Registration Tool (regasm.exe). The Type Library Exporter takes an assembly as input and produces the corresponding type library as output. The Assembly Registration Tool also produces a type library from a .NET assembly and registers the type library and its COM classes in the Windows Registry. Because we are concerned with more than just creating type libraries, let's focus on the Assembly Registration Tool.

The Assembly Registration Tool is yet another command-line utility. Let's take a look at some of its more common parameters. Table 3-1 identifies the parameters we are using in this section.

Table 3-1: Assembly Registration Tool Options

Options

Description

/regfile:RegFileName.reg

Prevents the normal COM registry entries from being entered into the registry. The RegFileName.reg contains the entries that would have gone into the Windows Registry.

Table 3-1: Assembly Registration Tool Options

Options

Description

/tlb:TypeLibFileName.tlb

Specifies the destination file for the newly generated COM type library. This switch cannot be used in conjunction with /regfile.

/u and /unregister

Unregisters any classes that have been registered from this assembly.

Let's go through a simple example to see how this tool is used. Consider the following .NET class.

// Assembly file name: Animal.dll using System; namespace Animals {

public class CDog {

public void Bark() {

Console.WriteLine("Woof Woof");

We compile this class to Animal.dll and run it through the Assembly Registration Tool with the following syntax: regasm /tlb:animal.tlb animal.dll. Next, if we look at the resulting type library, we find something similar to the following:

Library Animals {

CoClass CDog {

[default] interface _CDog;

interface Object;

interface _CDog : IDispatch {

HRESULT ToString([out, retval] BSTR* pRetVal); HRESULT Equals([in] VARIANT obj,

[out, retval] VARIANT_BOOL* pRetVal); HRESULT GetHashCode([out, retval] long* pRetVal); HRESULT GetType([out, retval] _Type** pRetVal); HRESULT Bark();

Let's start off by examining the CoClass definition of CDog. Notice there are two interfaces: _CDog, and _Object. .NET supports single inheritance by allowing one object to inherit members of another class. In .NET, each class inherits from System.Object either directly or indirectly. When the Assembly Registration Tool reads an assembly, it is able to extract the inheritance hierarchy for each public class. Members of each class in the inheritance tree are added as members of the class being evaluated. So when the Assembly Registration Tool sees that CDog inherits from System.Object, it adds System.Object's members to CDog.

As you can see, many of the names in the .NET namespace map directly into the type library. For instance, the namespace Animals maps directly to the library name. In addition, the class name CDog maps directly to the CDog CoClass. There are circumstances where a type name in an assembly cannot map directly into the type library. In .NET, a type name can be reused throughout multiple namespaces. The class CDog can exist in the Animals namespace and in the Mammals namespace. To understand how the Assembly Registration Tool handles this naming conflict, let's modify our assembly to contain the Mammals namespace.

// Assembly file name: Animal.dll using System; namespace Animals {

public class CDog { public void Bark() {

Console.WriteLine("Woof Woof");

namespace Mammals {

public class CDog {

public void RollOver(){

Console.WriteLine("Rolling Over");

If we repeat our previous step, we get something similar to the following type library:

Library Animals {

CoClass CDog {

[default] interface CDog; interface Object;

interface CDog : IDispatch {

// .. Declaration of System.Object's members HRESULT Bark();

CoClass CDog_2 {

[default] interface CDog 2; interface Object;

interface CDog 2 : IDispatch {

// .. Declaration of System.Object's members HRESULT RollOver();

Notice that the Assembly Registration tool has added an underscore and 2 to the second instance of CDog in the assembly. Because Animal.CDog is defined first in the source code, it gets to keep its original name in the type library. Subsequent uses of the CDog name are suffixed with an underscore and a running index number. If CDog were an interface instead of a class, the same rules would apply. Be forewarned, however, that this naming convention could change in future releases of the framework.

There are a few limitations when converting assemblies to type libraries. For instance, only public classes and interfaces can be exported. In addition, any public class you wish to export must implement a constructor with no parameters. Any static members such as fields and methods cannot be exported. If you wish to provide access to a static member, you must wrap it in an instance-level method call.

Note If you have classes that meet these criteria and you still do not want to make them available to COM, you can use the System.Runtime. InteropServices.ComVisible attribute. The ComVisible attribute can be used to hide assemblies, classes, and interfaces from COM. Although this attribute takes a true or false value, it cannot be used to make an otherwise invisible type available to COM. Types that are marked private, internal, or those that do not have a default constructor (no parameters) cannot be made visible to COM, regardless of the value of the ComVisible attribute.

Assemblies contain more than just the definition of their types. As you have learned from Chapter 1, assemblies contain a four-part version number, a simple string name, the originator's public key, and, optionally, a strong name if the assembly is shared among multiple applications. When an assembly is converted to a type library, a unique TypeLib ID must be created for COM clients to find the type library in the registry. During the conversion process, an assembly's simple name and originator key are used to generate the new TypeLib ID. A given simple name originator key always generates the same TypeLib ID.

Type libraries also contain version numbers. An assembly's major and minor version numbers are converted to the type library's major and minor version numbers. Build and revision numbers from an assembly are discarded. If an assembly does not contain a version number, the Assembly Registration Tool and the TlbExp utility use 0.1 for the type library version number.

Was this article helpful?

0 0

Post a comment