Flylib.com

Books Software

 
 
 

Guidelines for Migration


Guidelines for Migration

When you plan to migrate to .NET, you must remember the following guidelines:

  • Select an appropriate migration strategy that allows you to reduce the risk of migration. In adverse situations, you may migrate from your existing application and the converted code may not run as desired.

  • Migrate to .NET in a way that allows you to retain existing COM code. You need to consider which parts of the unmanaged application need to be migrated and which parts can interoperate with the .NET application.

  • Obtain the advantages of the features that .NET provides. Migration is not of much use if you are not planning to avail of the new features that .NET provides.

  • Select the right code to migrate. It is important to select the right code or you may find it difficult to integrate the new code with the existing application. It is best to perform a code path analysis before migration.

  • Select an operating system that utilizes all the features of .NET. For example, Windows 98, Windows NT, and Windows ME do not provide all the .NET features. It is better to use Windows 2000, 2003, or XP to use all the features of .NET.



Migration Process

A migration process requires a lot of effort, several resources, and time. You need to perform a cost/benefit analysis to check the feasibility of migration. The best practice for migration is to initially migrate DLLs, modules, and classes. You should migrate ADO, ActiveX, or COM components later. The migration wizard used for migrating applications to the .NET environment does not fully convert applications to .NET. For example, the migration wizard does not support the following functions;

  • OLE container code

  • Dynamic data exchange

  • ActiveX documents

  • Web classes

  • Graphics

  • Drag-and-drop

To migrate an application to the .NET environment, you need to:

  1. Understand the existing application before you start modifying it. You need to know the application's working and functionalities. You can acquire this information from the existing documentation of the application.

  2. Decide the features that you need in the application. In addition to existing functionalities, you also need to decide the additional features that you should include based on the client's requirements.

  3. Delete all the unnecessary or repetitive code in your application. This saves effort and costs when you migrate the application to .NET.

    Tip 

    Use a code analyzer to delete unused code.

  4. Declare variables explicitly before you start the migration process. Declaring variables optimizes code and makes it robust. It also helps in the migration process using the migration wizard.

  5. Perform the migration using the migration tool.

  6. Solve the upgrade issues that might occur when the Upgrade wizard is unable to convert all parts of code successfully.

  7. Upgrade syntax and controls. Syntax errors may occur when you migrate your application because .NET applications have different syntax when you compile. You need to use the latest syntax and controls to take advantage of the .NET technology.

  8. Run the code after fixing all the errors. Check if the code runs according to requirements.



Interoperability Framework

Migrating an entire application to .NET may not be feasible . You can use existing COM components with new or migrated .NET applications .NET provides an interoperability framework to facilitate interoperability with COM components. Code in a COM component is unmanaged but code in a .NET application is managed.

.NET supports the following features for interoperability between managed and unmanaged code:

  • Object binding: Supports both early and late binding of components.

  • Data assembling and translation: Manages data type conversion among managed and unmanaged data types. For example, an integer type in VB 6.0 is of 16 bits but an integer type in VB.NET is of 32 bits.

  • Managing objects: Manages objects during their lifetimes and ensures that you release the objects or send them for garbage collection.

  • Object identity: Implements the identity rules of COM objects so that the COM components can be identified when you refer to the COM components from .NET applications.

  • Exception handling: Translates the values of COM HResult to .NET exceptions.

You can perform interoperability in two ways:

  • By calling unmanaged code from managed code

  • By exposing managed code to unmanaged code

Calling Unmanaged Code from Managed Code

You can call unmanaged code from managed code in three ways. The technologies that allow this interaction are:

  • Platform Invoke that allows you to call any function in any unmanaged language if its signature is redeclared in managed code.

  • COM interop using Runtime Callable Wrappers (RCW) allows you to call COM components in any managed language, such as VB.NET or C#, which behaves similar to normal managed components.

  • C++ interop allows the direct use of flat APIs and COM APIs. This powerful feature is specific to C++.

Platform Invoke Feature

You can call unmanaged code from managed code using the platform invoke feature. You can use the DLLImportAttribute class to identify the name of the DLL file and the function that you need to use. You need to declare the prototype of the function that you need to call from the unmanaged DLL in .NET code. When you call only a few unmanaged methods , it is better to use platform invoke. When you use a small part of unmanaged code and the remaining code is written in any other managed language, then the use of platform invoke will require an extra effort. For example, when you call the Win32 API functions that the Windows operating system exposes, you are performing platform invocation.

COM Interop Using RCW

You use COM interop to call methods of COM components in .NET applications because COM interop imports COM types to the .NET application. COM interop also assists forward compatibility to allow you to call managed .NET code from COM clients. COM interoperability is two ways. This means that .NET components can call COM components and vice-versa. When you talk about calling COM components from .NET clients , it is important to understand what are RCWs. All Win32 COM components are unmanaged code because the components were designed before CLR. CLR does not recognize unmanaged code. The managed components require that the other components with which they are interacting should be CLR-compliant. CLR places a wrapper called RCW around the COM component whose method you are calling in managed code. Figure 2-5 shows how RCW handles interoperability:

click to expand: this figure shows how rcw facilitates interoperability among com components and .net clients.
Figure 2-5: Run-Time Callable Wrappers

RCW changes COM metadata to .NET metadata. You use the type library importer (tlbimp) tool to perform this conversion. This tool is available in the .NET Framework Software Developer Kit. tlbimp tool reads metadata from a COM type library and creates a similar .NET interop assembly to call the COM component. The main functions of RCW are:

  • Managing interaction between the COM component and .NET

  • Creating and binding the COM object

  • Converting unmanaged COM interfaces to a managed form

  • Translating and assembling data among environments

  • Administering the wrapped COM object during its lifetime

In .NET client applications, you refer to COM components directly but actually, you use a RCW to fetch the objects in unmanaged code. To add a reference to a COM component to a VB.NET project:

  1. Select Project ->Add Reference from the menu bar.

  2. Select the COM tab in the Add Reference dialog box.

  3. Select the component from the list and click Select. If the desired component is not present in the list, select the Browse button to search the component. This adds the selected component to the Selected Components list. Click OK.

When you build the project, the runtime creates Interop.ComponentName.dll in the project's /BIN folder. The runtime derives the name of the DLL from the component’s name.

You can use the tlbimp method or the direct reference method to call the COM component but it is important to know when to call which method. The reasons for calling a particular method are:

  • To use a COM component that is to be shared with multiple projects, it is best to use tlbimp. Tlbimp allows you to sign the resultant assembly and store it in the Global Cache assembly, which allows you to create a RCW.

  • To create a COM component that is not to be shared with other projects, it is best to use direct reference.

  • To control the advanced details of the assembly, such as version number or namespace, you use tlbimp. You do not acquire control over advanced details if you use direct reference.

Note 

To learn more about COM interoperability, see the COM Interop ReferencePoint.

C++ Interop

You can call unmanaged flat APIs from managed code through C++ interop used only in C++. You use C++ interop when you call COM components, depending on the Interface Definition Language (IDL) file that contains a number of interface definitions. C++ interop allows direct access to COM APIs. To call complex unmanaged APIs or simple unmanaged APIs that change while developing managed code, it is better to use C++ interop, which allows you to directly access unmanaged APIs.Figure 2-6 shows the flow diagram for calling unmanaged APIs:

click to expand: this figure shows the flow to call unmanaged apis. the unmanaged api type converts to com interop.
Figure 2-6: Flow Diagram for Calling Unmanaged APIs

Exposing Managed Code to Unmanaged Code

Using COM interop, you can expose the public managed class to unmanaged code. Although managed and COM object models are different, exposing a managed API as a COM API is easy because COM interop performs all the tasks . Managed code provides a few, new features that do not have corresponding features in COM code. COM clients can call exposed .NET code but COM clients do not have direct access to .NET code. To use a .NET component from a COM client, you create a proxy COM Callable Wrapper (CCW). COM components do not target the CLR and so cannot call managed code directly. You can solve this problem using a proxy. The proxy, which calls managed code from unmanaged code, is COM Callable Wrappers. Figure 2-7 shows how CCW handles interoperability while calling managed code from an unmanaged environment:

click to expand: this figure shows the ccw created when com clients call .net components.
Figure 2-7: COM Callable Wrapper Functionality

The two requirements that you need to meet before creating a .NET class that COM clients use are:

  • Defining an interface in .NET code and making the class implement the interface. When you implement the functionality through interfaces, the implementation provides key advantages to COM clients. Interfaces remain consistent with older versions while generating CCWs in .NET.

  • Declaring the classes as public that are noticeable to the COM clients. The tools through which you create CCW also define types based on public classes. The methods, properties, and events that COM clients use follow the same rules.

You can also sign .NET assemblies containing classes that COM clients can use with a cryptographic key pair. You sign the assembly with a strong name. .NET ensures that nobody tampers with the code in the assembly after you publish the assembly. All global assemblies, which are distributed among different clients, are required to follow this, though COM clients can call unsigned assemblies. You should ensure that you sign all the assemblies, including the private assemblies. This creates improved class IDs (CLSIDs) for managed classes and ensures that collisions do not occur between classes in different assemblies. The main functions of CCW are:

  • Managing interaction between COM and managed code

  • Creating and binding unmanaged code

  • Translating and assembling data among environments

  • Administering a .NET component during its lifetime

  • Translating the exceptions in .NET to COM HResult values