VB Migration Partner

A smart approach to 3rd-party ActiveX control conversion

The vast majority of VB6 business applications use one or more 3rd-party (non-Microsoft) ActiveX controls. It is therefore essential that the VB6 conversion software of your choice be able to correctly convert these controls to .NET with a cost-effective approach.

This document illustrates how VB Migration Partner can perform this task using an innovative approach based on wrapper classes, and intends to prove that - unlike more traditional approaches based on code transformations and mapping techniques - only wrapper classes can account for all minor and minor differences between ActiveX and .NET controls, can generate concise and efficient code, and don’t cause bottlenecks in the migration project.



Table of Contents

Why ActiveX control migration and replacement
Challenges in ActiveX control replacement
How Upgrade Wizard deals with ActiveX controls
How VB Migration Partner deals with ActiveX controls
How other VB6 conversion tools deal with ActiveX controls
Comparing ActiveX replacement techniques



ActiveX control migration and replacement

In describing how VB Migration Partner and other similar tools work it is essential to agree on what “converting an ActiveX control to .NET” really means. In fact, there are two distinct levels for this conversion. For the sake of clarity we will use the terms ActiveX migration and ActiveX replacement, even though in a somewhat arbitrary fashion. In the context of this document:

  • ActiveX control migration is the process of generating VB6 forms into .NET forms that still reference the same ActiveX control, via COM Interop.
  • ActiveX control replacement is the process of substituting the migrated ActiveX control with a pure .NET control, be it a native Microsoft .NET control, a 3rd-party .NET control, or a custom-made .NET control.

ActiveX migration is made possible by COM Interop, the portion of .NET Framework that allows .NET apps to communicate with COM components and ActiveX controls. COM Interop is a great technology that works unbelievably well considering that COM and .NET are completely different worlds. However, COM Interop has several issues and shortcomings, which explain why ActiveX replacement is nearly always necessary.

In describing the ActiveX conversion process, it is useful to distinguish between two different kinds of ActiveX controls and components, depending on whether the ActiveX control is part of the user interface:

  • Invisible ActiveX controls are controls that you place on VB6 forms, so that you can set their attributes in the Properties window, yet they don’t produce a visible user interface at runtime. Examples of these controls are MSComm (for serial communications), WinSock (to TCP and UDP communications), or Microsoft Script Control.
  • Standard (visible) ActiveX controls are the usual controls that you used to enrich your VB6 apps with a better user interface, for example MSDataGrid, MSChart, MSCalendar. The majority of 3rd-party controls also belong to this categories, for example the VideoSoft VSFlexGrid, Apex TrueDBGrid, or FarPoint Spread.

COM Interop works very well with COM type libraries and ActiveX controls that have no user interface, therefore it is usually considered to be acceptable for migrated apps to preserve all references to type libraries and invisible ActiveX controls.

Conversely, COM Interop may have problems with more complex ActiveX controls, such as grids and charting controls. These controls may behave errantly or crash the application when hosted on a .NET form, therefore it is highly recommended that the migrated .NET application have no reference to the original ActiveX controls and that you replace all ActiveX controls with equivalent, fully managed .NET controls.

Even if your ActiveX controls don’t crash the application, many 3rd-party controls don’t display their UI elements correctly under Windows Vista and Windows 7, and presumably this problem is going to get worse in future operating system versions. If you want to prepare your application for the future, you should seriously take this problem into account.

Another reason for replacing ActiveX controls is that COM and ActiveX are inherently 32-bit technologies that don’t work well (or at all) under 64-bit platforms. While you are facing the task of converting your code to .NET, you should consider it as your best opportunity to get rid of any dependency from older 32-bit CPUs.

Databinding is another reason for replacing all ActiveX controls with their .NET equivalent. If the original VB6 control uses databinding to display and modify data in an ADODB.Recordset object, this control won’t work any longer if you replace the Recordset with the ADO.NET DataSet object. The same consideration holds true if your VB6 application uses other COM-based data access technologies. In general, if you are switching from ADODB, DAO, or RDO to ADO.NET, then you have to replace all your databound ActiveX controls with equivalent ADO.NET controls that are bound to the DataSet object.

Finally, ActiveX controls require special care in installation and deployment. If your .NET application depends on one or more ActiveX controls, then it will be subject to a form of the DLL Hell problem that has plagued VB6 developers for years. If another application that uses a different (minor) version of the same control is installed after yours, odds are that your application stops working or behaves errantly. For this reason, your final goal should be a .NET application that has absolutely no dependency on COM and ActiveX components.



Challenges in ActiveX replacement

Regardless of how similar a VB6 control and its corresponding .NET control can be, there will always differ in tons of major and minor details, including

  • Different member name: for example, the SetFocus method is replaced by the Focus method under .NET, hWnd corresponds to Handle property, and so forth.
  • Different syntax: all events and many methods have a different syntax under .NET.
  • Different behavior: for example, the ValidateControls VB6 method can be translated with the Validate method under .NET, but the former raises an error whereas the latter just returns False if validation fails.
  • Different appearance: there can be minor differences in how the VB6 and .NET controls display themselves, and sometimes these differences cannot be ignored. For example, System.Windows.Forms.Button .NET control of same size and same caption as a VB6 CommandButton has a smaller client area and therefore often truncates its inner caption.
  • Different event order: .NET controls don’t necessarily fire the same events as VB6 controls, or they fire events in a different order; for example, the order in which the GotFocus and LostFocus events fire under VB6 and .NET is different, a detail that may lead to many subtle bugs.
  • Missing members: for example, .NET controls expose neither graphic methods (e.g. PSet, Line, and Circle) nor drag-and-drop members that are comparable to those you can find in VB6 controls.
  • Missing features: .NET controls don’t expose DDE-related members; position and dimension properties are always expressed in pixels and .NET offers no support for user-defined coordinate systems; also, no .NET property can replace the AutoRedraw property, just to mention a few key missing features.
  • Late binding: the migrated control should work fine even if the name or syntax of one or more members has changed from VB6 to .NET
  • Split and combined members: some VB6 members have been split in two different .NET members; for example, the ZOrder VB6 method maps to either BringToFront or SendToBack .NET methods. Likewise, VB6 members may have been combined into a single .NET property, method, or event, as is the case with the QueryUnload and Unload VB6 events that have been merged into the FormClosing .NET event.
  • Databinding: VB6 controls can be bound to ADODB, DAO, or RDO data source – for example, the ADODB.Recordset object or the ADODC control - whereas .NET controls can be typically bound only to ADO.NET sources (e.g. DataReader, DataView, or DataSet objects).

NOTE: Please visit our Resources section for a more complete list of the differences between VB6 and .NET built-in controls. The majority of these differences also affect ActiveX controls.

When you replace an ActiveX control with an approximately equivalent .NET, you must find a way to account for all these (and other) differences, and you are eventually going to write plumbing code to force the .NET control to behave like the original VB6 code, so that you preserve functional equivalence and the application’s look-and-feel.

Unfortunately, no conversion software on the market can write this plumbing code for you, because there are hundreds of ActiveX controls around and each of them supports hundreds of properties, methods, and events. It is simply impossible to account for all members of all existing ActiveX controls out there.

Therefore, when evaluating VB Migration Partner or a similar conversion tool from another vendor, the question to ask should not be “Does your software support the XYZ ActiveX control?” Instead, a more appropriate question is “How much extra code am I expected to write to support the XYZ ActiveX control?

In the remainder of this document we will describe how VB Migration Partner answers this question and compare its approach with the solutions offered by other VB6 conversion tools.



How Upgrade Wizard deals with ActiveX controls

Before describing the approach that VB Migration Partner adopts to migrate ActiveX controls and eventually replace them with .NET controls, let’s quickly revise how Upgrade Wizard works.

Visual Studio Upgrade Wizard – included in Visual Studio 2008 and previous versions, but not in Visual Studio 2010 – is able to migrate ActiveX control references to .NET, but not to replace them with native .NET controls.

Behind the scenes, Upgrade Wizard runs the AxImp utility to generate a DLL that contains the binary wrapper for that control. (AxImp is a command-line tool that is part of .NET Framework SDK). Next, Upgrade Wizard converts individual VB6 forms and generates .NET forms that use this binary wrapper.

Technically speaking, Upgrade Wizard creates .NET applications that indirectly reference the original ActiveX control through a wrapper class that is exposed by the AxImp-generated DLL. For all practice purposes, generate .NET applications use the original ActiveX controls, with all the issues that this approach brings with it. It is worth noticing that the AxImp-generated wrapper class is compiled in the DLL and you can’t see nor modify its source code.

As explained previously, it is highly recommended that you replace these ActiveX references with references to native .NET controls. Unfortunately, Upgrade Wizard offers no support for this replacement stage. In practice, you have to manually replace all ActiveX controls with the .NET control of your choice.

Worse, manual replacement usually introduces tons of syntax and compilation errors – depending on how different the original ActiveX control and the selected .NET control are. You have to manually fix all these errors before proceeding; again, Upgrade Wizard doesn’t offer any kind of support for this lengthy and error-prone job.

In summary, Upgrade Wizard does an acceptable job as far as ActiveX control migration is concerned, but offers no support for ActiveX control replacement. Given that replacement is the final stage of all real-world migration projects, it is safe to conclude that Upgrade Wizard isn’t a serious candidate tool for dealing with ActiveX controls.



How VB Migration Partner deals with ActiveX controls

VB Migration Partner fully supports over 60+ controls right out-of-the-box; including all controls that come with VB6 and many others that you could download from Microsoft web site. This group includes the Threed library (SSButton, SSCheck, etc.), the MSWLess library (WLText, WLCombo, etc.), and the Microsoft Script Control.

NOTE: the only Microsoft controls that VB Migration Partner doesn’t support are: the OLE container control, the DataRepeater, and the Coolbar.

All controls that aren’t part of the abovementioned group should be considered as not directly supported by VB Migration Partner.

Immediately after you install VB Migration Partner, it knows how to neither migrate nor replace these unsupported ActiveX controls: if you convert a VB6 form that contains unsupported controls, VB Migration Partner replaces those controls with generic VB6Placeholder controls, which look like red rectangles on the converted .NET form.

The inability to migrate third-party controls can be disappointing at first, especially because even the lowly Upgrade Wizard can perform this task without any manual labor. On the other hand, as you’ll see shortly, VB Migration Partner’s approach is far more flexible, allows you to save time and effort, doesn’t cause bottlenecks in the migration process, and greatly simplifies the debug and test phases.



ActiveX control migration

Here’s a practical example: let’s say that you want to add support for the MSCalendar control. (This example is for illustration purposes only, because MSCalendar is the list of controls that VB Migration Partner natively supports.)

The first step towards ActiveX control migration is launching AxWrapperGen, a utility that is installed with VB Migration Partner. This command-line tool takes the name of the *.ocx file that contains the ActiveX, the name of the VB.NET project to be created (/project option), and the path of the folder where the VB.NET project will be created. For example, this command

        AxWrapperGen c:\windows\system32\mscal.ocx /out:c:\myapp /project:NetCalendar

creates a wrapper class for the mscal.ocx ActiveX control (the MSCalendar control), as part of a VB.NET project named NetCalendar stored in the c:\myapp folder.

The NetCalendar.vbproj project contains two classes, VB6Calendar and VB6Calendar_Support. The former inherits from AxMSACAL.AxCalendar and wraps the ActiveX control; the latter is an auxiliary class that is only used during the migration step to control how VB Migration Partner generates code. (This support class isn’t relevant for our discussion and won’t be analyzed in this article.)

NOTE: AxWrapperGen generates a pair of classes for each ActiveX control defined in the OCX file. In this example only a class pair was generated, because the mscal.ocx file contains only the MSCalendar ActiveX control.

Like the Upgrade Wizard, AxWrapperGen runs the AxImp utility behind the scenes. The resulting NetCalendar VB.NET references the two DLLs that were generated by AxImp, MSACAL.dll and AxMSACAL.dll:

This is how the VB6Calendar class looks like:

        <VB6Object("MSACAL.Calendar", DependsOnAssemblies:="CodeArchitects.AxVBLibraryOCX.dll,MSACAL.dll")> _
        Public Class VB6Calendar
            Inherits AxMSACAL.AxCalendar
            ...
        End Class

For the most part, the code inside the VB6Calendar class consists of simple wrapper properties and methods that delegate to the corresponding property or method exposed by the inner ActiveX control (the AxMSACAL.AxCalendar class). For example, this is how AxWrapperGen generates the code for the FirstDay property:

        Public Property FirstDay() As Short
            Get
                Return MyBase.FirstDay
            End Get
            Set(ByVal value As Short)
                MyBase.FirstDay = value
            End Set
        End Property

AxWrapperGen knows that some standard VB6 properties and methods correspond to .NET members with different name:

        ' The VB6 SetFocus method maps to .NET Focus method
        Public Sub SetFocus()
            MyBase.Focus()
        End Sub

AxWrapperGen is also aware that VB6 members that have to do with position and size can be affected by the current value of the ScaleMode property of the parent form; the wrapper property or method for these elements calls methods in VB Migration Partner’s support library:

        Public Shadows Property Left() As Single
            Get
                Return VB6Utils.FromPixelX(Me, MyBase.Left, False)
            End Get
            Set(ByVal Value As Single)
                MyBase.Left = VB6Utils.ToPixelX(Me, Value, False)
            End Set
        End Property

In many cases, the code that AxWrapperGen generates compiles correctly and without errors. For more complex controls – most notably, grids and charting controls – you may need to manually fix some statements to compile or run correctly. (For more details, see the remarks in the “Instructions” region, at the top of the generated wrapper class and read this whitepaper.)

When all fixes are in place, you can compile the project, generate the NetCalendar.dll assembly, and manually copy this DLL to VB Migration Partner’s setup folder.

When VB Migration Partner runs, it scans all the DLLs in this folder, looks for classes that are marked with the VB6Object attribute, and takes note of the first argument of this attribute. From now on, VB Migration Partner knows that all MSACAL.Calendar ActiveX controls must be rendered as instances of the NetCalendar.VB6Calendar class, which in turn inherits from (and work as a wrapper for) the AxMSACAL.AxCalendar ActiveX control:


Please notice that you only need to run AxWrapperGen only once for each given ActiveX control used in your application. These wrapper classes are just VB.NET classes, therefore you can then group all wrappers in a single DLL, or you can compile them as part of the main VB.NET application if you don’t want to distribute any additional DLL.

VB Migration Partner’s approach to replacing ActiveX control might sound a bit contorted when described in abstract terms, but in practice it works like a charm, as this feedback can attest:

One of the major obstacles we found during the migration was the presence of Infragistics’ DataGrid 3.1 in virtually all forms. Code Architects’s support team helped us in authoring a .NET custom control (based on DevExpress’ XtraGrid) that implements all the properties, methods, and events that were used by ProdWare (among the many exposed by DataGrid) and that faithfully reproduces their behavior so that the resulting .NET code can be considered as functionally equivalent to the original VB6 code. By applying the right attribute to our control, VB Migration Partner was able to automatically replace all occurrences of the Infragistics’ grid with our control.

Dr. Italo Lunati - Elabora srl, makers of ProdWare

Here are the words from another user who fought (and won) against a large number of ActiveX controls:

In 1995 we realized a client/server application in VB3 using several third party controls, such as Crystal Report, Formula 1, and Crescent QuickPak. Over the years the software was greatly enhanced with new features and was ported to VB5 and then to VB6. [….]

[….] the included AxWrapperGen tool allowed us to create wrapper classes that guarantee the correct working of a few VB6 controls that aren’t directly supported under VB.NET. We estimate that this tool alone spared us several man months of hard work.

Finally, I’d like to thank Code Architects’ technical support team, who supported us through our endeavors, in a professional and efficient way. They and their software allowed us to complete the migration of our flagship application earlier than expected.

Marco Meneo - ProgeSoftware



ActiveX control replacement

At this point VB Migration Partner knows how to migrate the ActiveX control, yet the result of the migration is a .NET application that still depends on the original ActiveX control. In fact, the original ActiveX control must be installed with the proper design-time or runtime license for migrated apps to work correctly.

Let’s see now how to instruct VB Migration Partner to generate a .NET application that has no dependency on legacy ActiveX components. The wrapper class that we generated in the previous step greatly reduces the effort that is needed to complete the replacement step. In fact, the wrapper class works as a mediator between the .NET client project and the AxCalendar class (the actual ActiveX control), as shown in previous diagram. We can therefore modify the wrapper class without touching the .NET client project.

The first thing to do is replacing the VB6Calendar’s base class so that VB6Calendar inherits from a .NET control that we selected. In our example, we can make VB6Calendar inherit from System.Windows.Forms.MonthCalendar control, thus we need to change the Inherits statement as follows:

        <VB6Object("MSACAL.Calendar")> _
        Public Class VB6Calendar
            Inherits System.Windows.Forms.MonthCalendar
            Implements IVB6Control
            ...
        End Class

Also notice that we have dropped the DependsOnAssemblies property of the VB6Object, because our wrapper will have no dependency on any ActiveX control or DLL.

The change in the Inherits statement causes several compilation errors, because the MyBase object now points to a MonthCalendar control instead of AxCalendar, and these two controls have a different programming interface.

For example, the MonthCalendar control doesn’t expose a property named FirstDay (the weekday shown in leftmost column), even though its FirstDayOfWeek property performs the same job. The FirstDayOfWeek .NET property takes a System.Windows.Forms.Day enumerated value, whereas the original FirstDay VB6 property takes a 16-bit integer, therefore we need to perform a type conversion (edits are in boldface):

        Public Property FirstDay() As Short
            Get
                Return CInt(MyBase.FirstDayOfWeek)
            End Get
            Set(ByVal value As Short)
                MyBase.FirstDayOfWeek = CType(value, System.Windows.Forms.Day)
            End Set
        End Property

If the ActiveX control and the .NET control are similar enough, all necessary code changes are as simple as the one we have just seen.

Another important detail: you don’t strictly need to edit each and every member of the wrapper class to account for the different base class. For example, if your client .NET project doesn’t use the NextDay method, you can just remark out its inner statement(s):

        Public Sub NextDay()
            ' MyBase.NextDay()
        End Sub

Better yet, you can add a Throw statement and an Obsolete attribute:

        <Obsolete("MSCalendar.NextDay method isn’t supported")> _
        Public Sub NextDay()
            Throw New System.NotImplementedException()
        End Sub

The Obsolete attribute forces Visual Studio to treat all calls to unsupported members as compilation warnings, whereas the Throw statement ensures that all calls to these members cause a runtime exception. These two elements ensure that a call to NextDay from the .NET client application won’t go unnoticed.

You can now remove the project references to AxMSACAL.dll and MSACAL.dll files, so that the NetCalendar.dll assembly has no dependency on ActiveX legacy components and is ready to be compiled for 64-bit platform. The dependency diagram becomes:

For all practical purposes, all migrated .NET forms are now using the MonthCalendar control, via the VB6Calendar class. In case you haven’t noticed it, let’s emphasize that we can replace the ActiveX control without changing any single statement in the migrated .NET project!

The wrapper class approach has other advantages, some of which might not be obvious:

  • The wrapper class is fully independent of the main application, therefore ActiveX control replacement can be carried out by a different team of developers, in parallel with the developers that are working on the main application.
  • The number of edits on the wrapper class that are necessary to complete ActiveX control replacement depends only on the number and complexity of the members your main app actually uses; it doesn’t depend on how many times the ActiveX control is used in the original VB6 project. In real-world projects of medium or large size, this factor dramatically reduces the overall necessary effort.
  • The developers working on the wrapper class need to know nothing about the main application nor do they need to see its source code, therefore you can safely outsource this job to another company if you don’t have enough in-house resources, regardless of how strict your security policies are. (Code Architects offers this kind of service, by the way.)
  • Being standard VB.NET classes, you can easily include these modified wrapper classes in your main project, if you don’t want to distribute them as additional DLLs. This arrangement can sometime give you the additional flexibility you might need to work around special cases, undocumented behaviors, and so forth.

For more information about AxWrapper and how to create and refine wrapper classes, please read the ActiveX Controls and wrapper classes whitepaper.



How other VB6 conversion tools deal with ActiveX controls

At least another VB6 conversion tool on the market – Artinsoft’s VB Upgrade Companion (VBUC) – is able to convert ActiveX controls and replace them with equivalent .NET controls. Let’s see more in detail how such software works.

VBUC uses can use either of two approaches, depending on whether the ActiveX control in question is supported or unsupported.

When an ActiveX control is unsupported, VBUC behaves exactly like Upgrade Wizard. (This isn’t a coincidence, because Upgrade Wizard and VBUC share the same conversion engine.) In this case, VBUC runs AxImp behind the scenes to generate a binary DLL wrapper for the control, then VBUC generates .NET forms that use the ActiveX control via the wrapper. You can limit the number of manual edits in forms that use this control by means of mapping techniques, as described later.



Supported ActiveX controls

If an ActiveX is supported, then VBUC replaces the ActiveX control with a similar .NET control, either a .NET Framework control or a 3rd-party control. For example, it converts the Sheridan SSCommand ActiveX control to System.Windows.Forms.Button (a built-in .NET control) and Apex TrueDBGrid ActiveX control to ComponentOne C1TrueDBGrid. (As its name suggests, C1TrueDBGrid is the .NET version of the original Apex control.).

NOTE: As of this writing, VBUC supports 34 ActiveX controls, 17 from Microsoft (included in VB6 setup or downloadable from their site) and 17 from third-party vendors. The complete list of these controls is available here.

VBUC uses code transformations to solve some of the differences between an ActiveX control and its .NET equivalent control. This approach works well when resolving an ActiveX member into a .NET member with exactly the same behavior, but different name or syntax, but often brings to clumsy results in other cases. For example, consider this simple handler for the KeyPress event:

        Private Sub Text1_KeyPress(ByRef KeyAscii As Short) Handles Text1.KeyPress
            ' convert the pressed key to uppercase, but ignore spaces
            If KeyAscii = 32 Then KeyAscii = 0: Exit Sub
            KeyAscii = Asc(Chr(KeyAscii))
        End Sub

VBUC uses transformation techniques to translate the above code as:

        Private Sub Text1_KeyPress(ByVal sender As Object, _
               ByVal e As KeyPressEventArgs) Handles Text1.KeyPress
            Dim KeyAscii As Integer = Asc(e.KeyChar)
            ' convert the pressed key to uppercase, but ignore spaces
            If KeyAscii = 32 Then
                KeyAscii = 0
                If KeyAscii = 0 Then
                    e.Handled = True
                End If
                Exit Sub
            End If

            KeyAscii = Asc(Chr(KeyAscii).ToString()(0))
            If KeyAscii = 0 Then
                e.Handled = True
            End If
            e.KeyChar = Chr(KeyAscii)
        End Sub

which is more difficult to read and maintain than the original VB6 code.

NOTE: in some cases, VBUC reduces the amount of generated code by means of helper classes defined in its support library. This library is provided as C# code, therefore you can’t include such helper classes in your VB.NET projects and must provide it as a separate DLL to your customers.

In addition to delivering more verbose and obscure code, ActiveX conversion based solely on code transformation and helper classes suffer from more serious limitations, such as:

  • The code transformation approach can’t solve all cases of members with different behavior, and is inadequate to account for different event ordering, missing methods, or missing features.
  • VBUC code transformation rules are hard-coded and you can neither modify nor extend them. These rules are written in a proprietary language named Kablok; only Artinsoft consultants can write or extend these rules.
  • Code transformation techniques can only work if a control is referenced via a strong-typed variable (early binding); they fail miserably if your code uses Variant, Control, or Object variables (late-binding).


Unsupported ActiveX controls

As noted previously, VBUC only supports 17 controls from third-party (non Microsoft) vendors. With hundreds of commercial ActiveX controls released in the VB6 years, it’s quite likely that your application uses several ActiveX controls that VBUC doesn’t support. Let’s see what VBUC has to offer in this case.

For controls that aren’t included in the list of the 17 supported ActiveX controls, VBUC provides you with the ability to define a basic mapping mechanism that allows you to convert a given ActiveX control into a .NET control of your choice. For example, you can use this mechanism to replace all instances of the Sheridan’s SSRibbon control into instances of the System.Windows.Forms.CheckBox control.

The mapping mechanism allows you to define simple member name transformations, thus you can map the hWnd property into the Handle property, the Caption property into the Text property, and so forth. Unfortunately, this functionality can’t compensate for the many differences between ActiveX and .NET controls. For example, the basic mapping mechanism can’t account for missing members, missing features, and different event order. (For these issues you need VBUC code transformation rules written in Kablok, but you can’t author such rules.)

If a given member can’t be translated by means of the basic mapping mechanism described so far, VBUC retains the original member name and syntax, and generates .NET code that can’t compile or run correctly until you manually fix all the unresolved errors.

It is important to notice that the amount of manual labor that is necessary to convert unsupported ActiveX controls is roughly proportional to two factors:

  • the number of members that can't be correctly translated by means of VBUC basic mapping mechanism
  • the number of control instances that are used in the VB6 project.

The bottom line: the approach based on code transformations and simple mapping mechanism is inefficient for larger applications, because you have to manually fix the code in each form that contains one or more ActiveX controls.



Comparing ActiveX replacement techniques

We now have all the elements to compare the different techniques that you can adopt in ActiveX control replacement.

Visual Studio Upgrade Wizard confirms its reputation for being a “toy tool” that is good mainly for demo purposes: it automatically migrates ActiveX controls from VB6 to .NET forms but offers no support for ActiveX control replacement. In practice, you can’t use it to migrate VB6 apps that contain lots of ActiveX controls.

VB Upgrade Companion and VB Migration Partner offer different paths to ActiveX control migration and replacement. To help you decide which approach is better for your needs, we have prepared a comparison table. The top half of the table compares the features of each product, whereas the bottom half explains how these products face the challenges of ActiveX control replacement, as outlined in a previous section of this document.

Features Artinsoft
VB Upgrade Companion
Code Architects
VB Migration Partner
ActiveX migration Automatic It is necessary to run AxWrapperGen tool to generate a wrapper class. This step is necessary only once for each ActiveX control used by your application.
ActiveX replacement of supported 3rd-party controls VBUC directly supports 17 third-party ActiveX controls by means of code transformation techniques. VB Migration Partner supports 9 controls included in Sheridan ActiveThreedPlus suite. All other non-Microsoft controls require a wrapper class to be generated.
ActiveX replacement of controls that aren’t explicitly supported VBUC offers a basic naming mechanism to map ActiveX members to .NET members. Wrapper classes offer a standard and uniform approach to replace any ActiveX control.
Custom replacement rules for unsupported controls and features Only Artinsoft can create such rules, which are written in proprietary Kablok language. (End users can only author mapping tables.) Wrapper classes are written in plain VB.NET; any .NET developer can edit them to correctly replace any ActiveX controls.
Ability to replace ActiveX controls “in parallel” with the main migration project No – All compilation and runtime errors caused by ActiveX replacement must be manually fixed by editing the main application’s source code. Yes - A different team of developers can take care of ActiveX control replacement while other developers are busy at migrating the main application.
Amount of required manual effort The number of manual fixes is roughly proportional to the number of ActiveX instances in the main application AND the number of members and features used. The amount of labor on the wrapper class is proportional to the number of members and features used, regardless of how many ActiveX instances were in the original VB6 app.
Code readability and maintainability Code transformation often generate more verbose code that hampers readability and maintainability of the generated VB.NET application. Wrapper classes expose the same object model as the original ActiveX control, therefore the resulting .NET code is as readable as the original VB6 code (or more readable if code refactoring techniques had been enabled).
Easy of deployment You typically need to distribute an additional DLL containing the support library that many Microsoft or 3rs-party ActiveX controls require. You need to distribute one additional DLL containing all wrapper classes or you can embed these wrapper classes in the main project, if you wish.
Challenges in ActiveX replacement
Different name Supported Supported
Different syntax Supported Supported
Different behavior Supported only if the difference can be solved by means of basic code transformations. (*) Supported - wrapper classes give you the ability to change the behavior of the .NET control so that it perfectly mimics the original ActiveX control. (**)
Different appearance Not supported You can easily change basic look-and-feel of the inner control.
Different event order Not supported Supported - by editing the code in the wrapper class you can fire events in any order as well as fire events that the .NET control wouldn’t normally fire. (**)
Missing members Supported in some cases, by means of helper methods in a separate C# support library. (*) Supported
Missing features Not supported - code transformations cannot account for missing features such as graphics, user-defined coordinate systems, drag-and-drop, DDE, etc. If necessary, you can add missing features by extending the wrapper class as you see fit. (**)
Late binding Not supported Supported
Split members Supported in some cases (*) Supported
Combined members Supported in some cases (*) Supported
Databinding Supported in some cases (*) Supported


(*) We suggest to ask Artinsoft whether a specific member or feature exposed by a given ActiveX control is preserved after the replacement with a .NET control, and the degree of equivalence with the original control in terms of functionality, behavior, and appearance.

Also notice that these issues cannot be solved by means of the simple mapping mechanism available for controls that aren’t explicitly supported, that is, any ActiveX control other than the 17 third-party ActiveX controls that VBUC supports out-of-the-box.

(**) It’s easy for us to prove this claim. All controls in VB Migration Partner support library are actually wrapper classes of standard .NET controls in System.Windows.Forms namespace. Our controls support virtually all VB6 features – including graphics, drag-and-drop, DDE, double-buffering, user-defined coordinate systems. Any feature that we implemented in our standard support library can be implemented in user-defined wrapper classes, too.

ONE MORE BENEFIT: if you need to implement a feature that we already support in controls belonging to VB Migration Partner’s library – for example: graphic methods, drag-and-drop, or double buffering – we will save your time and efforts by showing you the relevant portions of our library’s source code.