How to achieve interoperability between Visual Basic 6 and .NET? Because the .NET Framework was designed from the ground up to communicate with COM components, the process should not be difficult; as a matter of fact, you will be able to access .NET components and assemblies from VB6 or viceversa by using the approaches and techniques described in this chapter.
Because this will enable you to identify the functional components of the application, and to build a more effective plan for the overall upgrade process. It also helps you to improve your application by identifying redundant or unused code modules that should be eliminated to reduce the amount of work that will be required for the upgrade. After you identify the components that must be upgraded to Visual Basic .NET and those that can remain in Visual Basic 6.0 (either temporarily or permanently), you can begin to create an effective interoperability between components.
The .NET Framework was designed from the ground up to interoperate with COM. COM components can call .NET assemblies, and vice versa. Furthermore, .NET assemblies can be built to be referenced just like COM components are referenced. To do this, you build your assembly so that it is COM-callable, and your code will be able to reference the assembly’s functionality and interfaces.
COM-callable assemblies can be referenced from Visual Basic 6.0 applications as if they were ordinary COM components. In this case, interoperability may be as simple as referencing the correct assembly’s type library (.tlb file) and accessing the desired functionality.
On the other hand, to access Visual Basic 6.0 code from Visual Basic .NET clients, you must expose the Visual Basic 6.0 code as a COM component, and then reference it as such from the Visual Basic .NET client.
There are two approaches: to use direct access through COM, requiring that the .NET assembly to be referenced is created as a COM-callable assembly, or to create a COM-callable wrapper using a .NET language for the functionality you want to access.
Every .NET component that is going to be accessed from Visual Basic 6.0 must be registered for interoperability in the system. Registration takes place at a global level and will make the component available to all Visual Basic 6.0 applications. An assembly is the primary building block of a .NET application and it can contain different classes that are available to COM clients. Registering an assembly will make the classes in a registered assembly available to all Visual Basic 6.0 applications on the system.
The process to register a .NET assembly and make it COM-callable involves creating a type library (.tlb) and including the corresponding entries in the system registry. This is easily accomplished from within the Visual Studio .NET IDE by setting the appropriate build configuration option.
You can follow these steps:
After completing these steps, you can reference any interface and public class contained within the assembly from your Visual Basic 6.0 project.
In such cases, you can create a COM-callable wrapper object in Visual Basic .NET, and reference the wrapper object from Visual Basic 6.0. Creating a wrapper involves several steps, including creating a type library (.tlb) file for the wrapper class and registering the class for COM interoperability.
Using wrappers gives you access to the full range of available .NET assemblies through Visual Basic .NET. It also allows you to better modularize your code by avoiding granular invocations of the .NET assemblies where they’re not necessary.
Marshaling is the process of packing and unpacking parameters and return values in a way that enables the execution of a cross platform invocation. As mentioned earlier, COM is the key to achieving interoperability between Visual Basic 6.0 and Visual Basic .NET. It is because of the presence of COM that data type marshaling becomes a non-issue in cases where components in different thread apartments interact. The .NET interoperability marshaling enables the interaction between different data types in managed and unmanaged memory. Interop marshaling is performed at run time by the CLR’s marshaling service when functions are invoked within the same COM apartment. When the interaction takes place between managed code and unmanaged code in a different COM apartment or a different process,both the interop marshaler and the COM marshaler are executed.
As mentioned previously, .NET uses a structured exception handling approach for indicating, and reacting to, both anticipated and unanticipated error conditions. This is not the case in Visual Basic 6.0. (Although the OnError handler provides a process that can be considered similar to exception handling, it does not behave the same way.)
Because interoperability between Visual Basic .NET and Visual Basic 6.0 is achieved using COM-based mechanisms, there is an inherent value, named HRESULT, which is passed back and forth between the Visual Basic 6.0 code and the .NET assembly. Even though this happens behind the scenes, it is still there. In Visual Basic 6.0, this value can be accessed through the Err.Number property. In Visual Basic .NET, this value is treated differently depending on whether or not the original exception is a standard exception.
You must inspect the Number property of the Visual Basic 6.0 Err object, and to select an execution path based on its value. This technique can also be applied to standard exceptions like overflow or divide-by-zero exceptions.
This is done through the RaiseEvent statement. These events can also be caught and handled by .NET code as if they were originating from a COM component. The Visual Basic 6.0 event producer code raises a Divide event whenever the DoDivide function is invoked and raises a Multiply event when the DoMultiply function is invoked. The consumer code, written in Visual Basic .NET, provides the event handlers OnDivide and OnMultiply to catch and handle each event whenever they occur.
The Visual Basic 6.0 App object provides a group of properties that can be used to specify parameters for the interaction and synchronization with an OLE Automation server during the invocation of one of its methods.
The first set of properties is related to the time that the application will retry a failed automation call request. After the specified time elapses, a customizable dialog box automatically displays in the application. This dialog box informs the user about the busy state of the OLE server. This behavior is controlled with the properties: OleServerBusyMsgText, OleServerBusyMsgTitle, OleServerBusyRaiseError, and OleServerBusyTimeout.
The second set of properties is related to the time an application will wait for an OLE Automation request to be completed. This group of properties works in a similar way to the previous group and includes: OleRequestPendingMsgText, OleRequestPendingMsgTitle, and OleRequestPendingTimeout.
The garbage collection mechanism is responsible for the invocation of component’s destructors when the component cannot be accessed by any executing code. This condition is reached when all references to the component have been released or belong to objects that are isolated from all running code.