How to stabilize a VBUC migrated application
by Olman Quesada, on May 20, 2021 1:41:56 PM
This post offers a quick summary of steps to be executed to achieve a successful migration project from Visual Basic 6 to .NET using the Visual Basic Upgrade Companion Tool.
Before reading this post, please read What not to do in a VBUC migration process article.
Automatic Conversion is the beginning
Using automatic tools to convert code from a source language (VB6) to a modern language like (VB.NET or C#) is just the first step before getting a workable converted application. Manual changes may be needed to stabilize portions of the application that will require human intervention.
What's needed to start stabilization
This list details what you need to start the manual stabilization:
- Green code of the .NET application (code generated by the VBUC tool)
- Any component used via COM Interop by the new .NET application must be installed/registered in the development machine (the machine where developers will stabilize the migrated application).
- Remember that any resource file (*.ini files, images, icons, custom string resource files) used by the VB6 application at runtime will be required by the .NET application as well.
Note: VBUC may convert some of the COM/OCX/ActiveX components used by the VB6 application to .NET equivalents. Any other component not included in the VBUC will be be used via COM Interop by the converted .NET application.
Once the above list is checked, then, the Compilation, Visual Equivalence and Functional Equivalence phases should be executed.
Getting green code compiling is the first stage to complete when trying to achieve
a workable .NET application (or Functional Equivalence application).
Make sure all references required by migrated .NET projects are correct and exists in current machine.
The screenshot below shows the Visual Studio Solution Explorer for a VB6 migrated application using MSWinsock library. The converted code still requires that library via COM Interop, and the library is properly installed/registered in the current development machine.
Every reference marked as not found by Visual Studio must be recreated manually by adding again the reference to the component.
Ensure Not-Upgraded-Elements are fixed
The VBUC converts library elements to their equivalent where possible. When there is no equivalent, the default behavior is to add a comment in the source code indicating that the following expression/statement was not converted and requires manual correction. This might cause a number of compilation errors that might hide other issues that need to be resolved manually.
For instance, the sample below shows properties of a VB6 Line Control that don't have an equivalent in .NET, and the VBUC generates a warning message indicating that. Those lines will cause a compilation error unless they get manually corrected by an equivalent.
//UPGRADE_ISSUE: (2064) Line property Line1.X1 was not upgraded. More Information: https://docs.mobilize.NET/vbuc/ewis#2064
this.Line1.X1 = 590;
//UPGRADE_ISSUE: (2064) Line property Line1.X2 was not upgraded. More Information: https://docs.mobilize.NET/vbuc/ewis#2064
this.Line1.X2 = 1590;
//UPGRADE_ISSUE: (2064) Line property Line1.Y1 was not upgraded. More Information: https://docs.mobilize.NET/vbuc/ewis#2064
this.Line1.Y1 = 500;
//UPGRADE_ISSUE: (2064) Line property Line1.Y2 was not upgraded. More Information: https://docs.mobilize.NET/vbuc/ewis#2064
this.Line1.Y2 = 2000;
All this manual effort can be mitigated by using "Upgrade Stubs generaion for non upgraded elements" Upgrade Option in the VBUC before generating the green code.
It makes all the not supported elements compile, avoiding an important amount of compilation errors and makes it easier to understand the required manual effort.
A solution can be implemented for each not-supported element in a unique location in the target source code, instead of changing all the not-upgraded member references.
Compile code & review errors (if any)
Despite executing the steps below, it's still possible to find compilation errors. For each one, research the cause of the compilation error by reviewing both the source and target source code.
This phase is divided into two different sub-areas: Visual Design and Visual Equivalence. Both of them are described below.
Once your converted code compiles, make sure all visual forms are displayed in the Visual Studio designer. For this, you'll need to open the .NET solution generated for the converted code, and then open each form in Visual Studio.
It's possible you will find some visual differences between both applications. Just remember, the UI measure unit changes from twips (VB6 standard unit) to pixels (.NET standard unit). Also, the look and feel of equivalent UI controls in .NET can be different, so some small changes might be required to make the app look identical to the original.
Runtime Visual Equivalence
This phase requires execution of the application and some basic testing: logging into the application, loading the main form or menu screen and basic navigation of the menus, ensuring the screens accessible from the main menu look the same and load the same data as in the original application.
Achieving this implies executing some tasks that will extend for the rest of the stabilization of the project:
Implementation of Stubs
In this phase, some stubs should be implemented to achieve Visual Equivalence, but some might remain for later phases.
The implementation of stubs could be done in later phases of the project as it may require running both applications, VB6 and .NET, to analyze differences and possible solutions for the problem.
Verification of error handling (C#)
The migration tools convert most of the error patterns correctly but some scenarios need manual refactoring (think about resume-next/resume/on-error-resume-next code patterns not supported in C#).
Revision of EWIs.
The VBUC tool adds comments to the migrated code named EWIs (Errors, Warnings and Issues). Those EWIs will not require a lot of modifications, but it's worth reviewing them and once addressed, remove the comment to have cleaner code.
Example of a EWI related to a Resume-Next non supported statement.
And again, debugging both applications, VB6 and .NET, side-by-side is key to understand behavioral differences in both platforms and discover potential solutions. On-Error-Resume-Next patterns are a good example of this: adding extra validations in .NET code could be the solution.
Other potential issues
Wrong behavior of COM objects, different event flow (between VB6 and .NET), memory leak (specially when relying on COM components or unmanaged calls - like Windows API) are potential issues in a migrated application that will require analysis and carefulness.
Functional Equivalence (FE)
"This term means that the converted application’s functionality is identical to the original application. This eases the transition to a more modern development environment as you are now able to add new features to your application." (taken from Mobilize Faqs ).
In this phase, not only all the above tasks (described in the VE phase) should be executed, but additional ones:
Testing the application is critical in this phase to find and provide solutions to any problem. This is the most important activity in the whole project and should be planned accordingly.
Test Plan and Test Cases
Defining a test plan and test cases is important to understand what should be the expected functionality of the migrated application.
Test cases should be executed in the original VB6 application to know what should be the output and validate the functionality to test, and then, against the .NET application. In my professional experience is not uncommon apply test cases that don't work in the VB6, and therefore will not work in the migration one.
Once the migrated application is stabilized, unnecessary references and dead code might be removed.