Using .NET Components in COM Applications

As you saw, using COM components in a .NET application was an easy task. Now, it's time to look at the reverse situation, in which you will call a .NET component from a COM application. This situation is not quite as clean as using COM components in .NET because you have to perform some tricks to get it to work.

Preparing the .NET Component for COM Clients

The first thing you want to do to have a .NET component that can be called by a COM client is to create your .NET component as you normally do. Start a new Class Library named NetInterop. Inside Class1.vb, you'll change the class name to EmpNet and enter the code that gives you the same functionality as the COM component from earlier. Your final code should look like this:

Public Class EmpNet
   Public Name As String
   Dim mdDOB As Date

   Public Property DateOfBirth() As Date
      Get
         DateOfBirth = mdDOB
      End Get
      Set(ByVal Value As Date)
         mdDOB = Value
      End Set
   End Property

   Public Function GetEmployee(ByVal piID) As String
      Dim sEmpInfo As String
      sEmpInfo = "Employee Name: " & Name & _
         "; Employee Date of Birth: " & mdDOB
      GetEmployee = sEmpInfo
   End Function
End Class

This code will work the same as the previous example that was written in COM: You have a field called Name, a property called DateOfBirth, and a method called GetEmployee that accepts a single parameter as an argument. The GetEmployee method returns a string to your client.

At this point, you need to build your assembly, so choose Build from the Build menu. Now, things are about to change.

You have compiled a .NET component, or assembly, and it is located in the bin directory of the project. You could leave it where it is, but you'll want to move or copy it for reasons that will be obvious in a moment.

You have several choices for your next step, but it is easiest if you create a new directory on your hard drive. For this example, I'll use C:Interop as the directory. Copy (or move) the NetInterop.dll to the C:Interop directory. What you now have is a .NET assembly in a directory all by itself.

To use this .NET assembly in a COM client application, you need to register the component in the registry. You might be tempted to reverse the process from before: Tlbimp.exe read the type library and created a .NET assembly. Conversely, there is a Tlbexp.exe that takes a .NET assembly and creates a type library.

Unfortunately, the type library that is created with Tlbexp.exe is not registered, so VB6 won't be able to automatically locate it. Further, the .tlb that is generated cannot be registered directly with Regsvr32.exe, the registration tool familiar to many VB developers.

Using Regasm.exe

The answer, therefore, is to use the Regasm.exe utility. This utility is designed to read an assembly and place the necessary type information into the registry so that COM clients can call the assembly.

First, if Regasm.exe is not in the path, you'll need to locate the Regasm.exe utility on your machine and either move it to a directory that is in the path, or type the entire directory name in front of the utility.

Next, open a command prompt and move to the directory where you placed the .NET component, which for this book's example is C:Interop. Type the following command at the prompt:

regasm /tlb:NetInterop.tlb NetInterop.dll

You should receive the following messages:

Types registered successfully
Assembly exported to 'C:InteropNetInterop.tlb', and the type
library was registered successfully

What you are actually doing in the command is two steps that could be done separately. The Tlbemp.exe mentioned in the previous section would generate a type library but not register it; the Regasm.exe with the /tlb switch creates a type library and registers it. The Regasm.exe also registers the assembly's types in the registry. You could run this as two separate commands, but this line allows you to register the type library and the types at the same time.

Creating the COM Client Application

The next step is to create a COM client that can use the component. Open VB6 and create a new Standard EXE application. When the project is open, select Project, References and look at the References dialog box. Scroll down until you find the NetInterop type library being displayed, and check the box next to it. As you can see in Figure 14.4, the reference is pointing to the type library file you created in the C:Interop directory. When done, click the OK button.

Figure 14.4. The .NET assembly shows up in the References dialog box, thanks to being registered by the Regasm.exe utility.


Now, add a button to your form, and add the following code to the project, and do not be alarmed if things don't appear to be working properly:

Private Sub Command1_Click()
    Dim Employee As EmpNet
    Set Employee = New EmpNet
    Employee.Name = "Jane Doe"
    Employee.DateOfBirth = "4/1/91"
    MsgBox Employee.GetEmployee(1)
End Sub

The first thing you might have noticed when you started typing was the complete lack of Intellisense. When you typed the period after typing Employee, you did not get a list of the available properties and methods. This is an artifact of the way .NET works in COM clients. You'll just have to code without Intellisense and trust that the application will work.

After you have typed in the code, you'll probably be tempted to click the Start button in the VB6 IDE to test the application. If you do this, however, you'll get the error shown in Figure 14.5.

Figure 14.5. The result of trying to run your COM client in the IDE, where it is unable to locate the .NET assembly it is calling.


You might be wondering what in the world is going on. After all, you've already lost Intellisense, and now you can't run the client application in the IDE. Actually, there's a good reason for the client application not running at the moment.

.NET works differently from COM. .NET typically assumes that either the assembly will be in the local directory, or it will be loaded in the global assembly cache. You read about the global assembly cache in Chapter 4, “Building Classes and Assemblies with VB .NET,” and you even placed an assembly in the GAC. If you had placed this assembly in the GAC, you would be able to run the client within the IDE.

Because your assembly is not in the GAC, however, .NET tries to serve it up from the local directory. The local directory to the VB6 IDE is the directory containing VB6.exe, which is C:Program FilesMicrosoft Visual StudioVB98 by default. Because this is obviously not the directory containing the assembly, the call fails.

You could have placed the assembly in the same directory as VB6.exe and run Regasm in that directory. However, in this example, you can fix the problem by compiling the COM application into the same directory holding the assembly—in this case, C:Interop. Choose File, Make Project1.exe, but make sure that you navigate to the same directory holding the .NET assembly you want to call. Once there, compile the program.

Now, from the C:Interop directory, run Project1.exe. The project will run normally, and display the results in the message box, as shown in Figure 14.6. Congratulations! You have just called a .NET component from within a COM application.

Figure 14.6. The COM application is able to call the .NET component when they are both in the same directory.


A Note on Registering

One thing you should realize is the difference between registering COM components and .NET assemblies. .NET allows you to store copies of an assembly in multiple locations on the hard drive. By default, .NET applications use assemblies in their local directories. This means that the local copy of the assembly will be used.

This is basically the opposite of how COM works. With COM, you can have multiple copies of a component on the hard drive, but applications will use only the copy that has been registered. By default, COM applications go to the registry to find the physical locations of components. COM handles instantiating the component either in the same process space as the application, or by creating the component in another process and returning a pointer to that component.

So, when you create a COM client calling a .NET component, it is .NET that is finding the component. Therefore, the client and component have to exist in the same directory, or the component has to be placed in the GAC for it to be located. This is why you cannot run your client applications in the VB6 IDE unless you move the component into the same directory as VB6.exe and register it there.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.140.79