EWIs
The following section provides useful information about the messages (comments) that will appear on your upgraded code and how to solve them.

Working with EWIs

The number of EWIs in your code depends entirely on your programming style and the size, type and complexity of files that you want to upgrade. As a general rule, forms usually have more issues than classes and modules, because forms have a richer object model and significant transformations must be applied when upgrading to Windows Forms.

Steps to fix a migration issue

This section shows the recommended steps to fix an error related to EWIs. The steps are:

Locate the source of the problem

To find the source of the problem, you can add some breakpoints a few lines before the code where the exception or the different behavior manifests itself. You need to do this in both the original VB6 code and the upgraded code so that you can compare to find out what is causing the problem or why the problem is occurring.

Understand the code purpose in the original VB6 application

The next step is to understand, in the original VB6 application, the functionality of the section of the code causing the problem. You can perform the following activities to understand the original behavior:
    1.
    Create small examples of code that use the same features.
    2.
    Execute step by step (debug mode), as many times as you need, the section of code causing the problem.

Identify a solution in .NET

Once the functionality of the original VB6 application is understood, the next step is to replicate the same functionality in the upgraded .NET application. Some recommendations for this are:
    1.
    Create small examples in .NET to replicate the VB6 functionality.
    2.
    Review the related .NET documentation on the web to determine how to achieve the same functionality in .NET.
    3.
    Ask your peers or a Mobilize.NET migration expert.

Implement the solution

If you already have a solution, you can implement it. Once you have modified the upgraded code and the found solution was implemented, you need to test your code to confirm that the behavior is the same as the original VB6 application. You can, also, review the rest of the upgraded code to determine if the same problem is present in other areas.

Mobilize.NET Customization (optional)

In some cases, you can consider Mobilize.NET Customization. Several factors must be taken into account at this point:
    1.
    Timing
      Will the current timeframe of the project allows the Mobilize Team to implement the required customization? Is the impact of the error large enough to justify it to be reported in order to be included in future releases used in future projects?
    2.
    Complexity
      Is there an opportunity to make the replacement in several places using another automated solution such as Regular Expressions?
    3.
    Rework required
      Are the manual changes performed at this point in the project so many that executing a code merge will imply too much additional work?

Document the solution

Once the solution is implemented and the problem is resolved, it is important that the solution is properly documented and stored in a shared knowledge base. This helps in cases where other developers run into the same issue and are able to access information on how to solve it.

EWIs Lists

In the following lists, you can see the most common EWIs. It is important to know that there are many other EWIs not described in those lists.

Warnings

The following are some of the most common warnings generated by the Visual Basic Upgrade Companion.
Code number
Description

Issues

The following are some of the most common issues generated by the Visual Basic Upgrade Companion.

ToDos

The following are some of the most common ToDos generated by the Visual Basic Upgrade Companion.

Notes

The following are some of the most common Notes generated by the Visual Basic Upgrade Companion.

Warnings

206 - Untranslated statement in %1. Please check source code

Description

This warning indicates an unexpected error during the automated upgrade process. As a result, some of the VB6 source code was not upgraded.

Recommendations

    Please report the issue to Mobilize Support.
    If the affected code is simple enough, you can manually write the missing code.

1003 - ParamArray %1 was changed from ByRef to ByVal

Description

In VB6, the Param Array keyword could be used to specify an arbitrary number of parameters for a declaration, sub, or function. ParamArrays were always passed by reference (ByRef). In Visual Basic .NET, ParamArrays are always passed by value; the Param Array keyword must be preceded by the ByVal keyword. When a parameter is passed by value, a copy of the variable is passed; when passed by reference, a pointer to the variable is passed. When passing by value, it is possible that the value of the variable may have changed and that the copy is out of date.

Recommendations

    Review the code to make sure that the variables being passed as parameters are not being changed between the time that they are set and the time that they are used in a procedure.
    If necessary, modify your code so that the procedure executes before the variables are modified.

VB6 Original Code

1
Private Sub Form_Load()
2
Dim myArray(0 To 2) As String
3
myArray(0) = "First"
4
myArray(1) = "Second"
5
myArray(2) = "Third"
6
7
Example myArray(0), myArray(1), myArray(2)
8
MsgBox myArray(1)
9
End Sub
10
11
Public Sub Example(ParamArray params() As Variant)
12
MsgBox "Second Parameter: " + params(1)
13
params(1) = params(1) + "_modified"
14
End Sub
Copied!

C# Upgraded Code

1
private void Form_Load()
2
{
3
string[] myArray = new string[]{"", "", ""};
4
myArray[0] = "First";
5
myArray[1] = "Second";
6
myArray[2] = "Third";
7
8
Example(myArray[0], myArray[1], myArray[2]);
9
MessageBox.Show(myArray[1], AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
10
}
11
12
//UPGRADE_WARNING: (1003) ParamArray params was changed from ByRef to ByVal.
13
public void Example(params object[] params_Renamed)
14
{
15
MessageBox.Show("Second Parameter: " + ReflectionHelper.GetPrimitiveValue<string>(params_Renamed[1]), AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
16
params_Renamed[1] = ReflectionHelper.GetPrimitiveValue<string>(params_Renamed[1]) + "_modified";
17
}
Copied!

VB.NET Upgraded Code

1
Private Sub Form_Load()
2
Dim myArray(2) As String
3
myArray(0) = "First"
4
myArray(1) = "Second"
5
myArray(2) = "Third"
6
7
Example(myArray(0), myArray(1), myArray(2))
8
MessageBox.Show(myArray(1), My.Application.Info.Title)
9
End Sub
10
11
'UPGRADE_WARNING: (1003) ParamArray params was changed from ByRef to ByVal.'
12
Public Sub Example(ParamArray ByVal params() As Object)
13
MessageBox.Show("Second Parameter: " & ReflectionHelper.GetPrimitiveValue(Of String)(params(1)), My.Application.Info.Title)
14
params(1) = ReflectionHelper.GetPrimitiveValue(Of String)(params(1)) & "_modified"
15
End Sub
Copied!

1044 - Sub Main in a DLL won't get called

Description

This EWI is generated when a non-EXE project has a Sub Main as a startup object.

Recommendations

    Since .NET DLLs do not have any method to execute it when the respective assembly is loaded, we have to add a static constructor and call the sub-main inside.
This will not be executed at the same time as VB6 but is the most similar behavior.

VB6 Original Code

1
Public Sub Main()
2
End Sub
Copied!

C# Upgraded Code

1
public class Class1
2
{
3
//UPGRADE_WARNING: (1044) Sub Main in a DLL won't get called.
4
public void Main()
5
{
6
}
7
}
Copied!

VB.NET Upgraded Code

1
Public Class Class1
2
'UPGRADE_WARNING: (1044) Sub Main in a DLL wont get called.'
3
Public Sub Main()
4
End Sub
5
End Class
Copied!

1047 - Application will terminate when Sub Main() finishes

Description

Standard EXE applications written in VB6 can be started either from the Main sub or a startup form. The use of the Main sub is a very common practice in large applications, because it allows the execution of initialization logic before the load of the main form of the application, and allows separation of this logic from the logic of the form.
When an application that uses the Main sub as a startup object is migrated using the VBUC, equivalent code is generated in .NET. However, due to differences in the behavior of VB6 and the .NET Framework, the applications behave differently. Some manual changes are required to achieve functional equivalence in this case.
In VB6, all the code in the Main sub is executed and the method ends, but the application continues to run while a form is displayed. In .NET, on the other hand, the application will exit as soon as the Main method exits, any open form at that point will be closed automatically.

VB6 Original Code

1
Public Sub Main()
2
Form1.Show
3
Dim x As Integer
4
x = 10
5
MsgBox x
6
End Sub
Copied!

C# Upgraded Code

1
//UPGRADE_WARNING: (1047) Application will terminate when Sub Main() finishes.
2
[STAThread]
3
public static void Main()
4
{
5
Application.EnableVisualStyles();
6
Application.SetCompatibleTextRenderingDefault(false);
7
Application.Run(Form1.DefInstance);
8
int x = 10;
9
MessageBox.Show(x.ToString(), AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
10
}
Copied!

VB.NET Upgraded Code

1
'UPGRADE_WARNING: (1047) Application will terminate when Sub Main() finishes.'
2
<STAThread> _
3
Public Sub Main()
4
Application.EnableVisualStyles()
5
Application.SetCompatibleTextRenderingDefault(False)
6
Application.Run(Form1.DefInstance)
7
Dim x As Integer = 10
8
MessageBox.Show(CStr(x), My.Application.Info.Title)
9
End Sub
Copied!

1049 - Use of Null/IsNull() detected

Description

In Visual Basic 6, the Null keyword indicates that a field contained no valid data and the IsNull function is used to test for Null. In addition, Visual Basic 6 support Null propagation when Null was used in an expression; the result of the expression would also be Null. This EWI indicates the use of the Null keyword or the IsNull function.

Recommendations

    In Visual Basic .NET, the Null keyword is still a reserved word, but it has no syntactical value, and the IsNull function is no longer supported.
    C# also reserves the null keyword, but it is not to be confused with Null in Visual Basic 6. Visual Basic's Null keyword indicated missing or invalid data in data field, which is the purpose of DbNull in the .Net Framework. C#'s version of null is closer to Visual Basic 6's Nothing keyword.
    Also, Null propagation is no longer supported in the .NET framework. When upgrading Visual Basic 6 applications avoid null propagation.
    During the upgrade, Null is converted to DBNull, and IsNull is converted to IsDBNull of which there are several variants: Visual Basic's IsDBNull function, the Convert.IsDBNull method, the DataTableReader.IsDBNull method, and the IDataRecord.IsDBNull method.
    The behavior of DBNull is slightly different than that of Null. Null could be used in functions and assignments as a Variant data type, however DBNull is a class and thus cannot be used as a direct replacement for Visual Basic's Null. DBNull.Value, however, can be passed as a value type in methods or assignments.
    Where Null was used with a Variant data type, the Variant is converted to Object during the upgrade; in these cases, depending on the context, it may be more appropriate to use the Nothing and the IsNothing function for VB.NET. For C# use the null keyword and compare it with null with the equality operators (== and !=).

VB6 Original Code

1
Private Function ResultTxt(var As Variant)
2
If IsNull(var) Then
3
ResultTxt = "Null"
4
ElseIf TypeName(var) = "Integer" Or TypeName(var) = "Double" Or TypeName(var) = "Long" Then
5
ResultTxt = CStr(var)
6
Else
7
ResultTxt = """" & var & """"
8
End If
9
End Function
Copied!

C# Upgraded Code

1
private string ResultTxt(string var)
2
{
3
//UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.
4
if (Convert.IsDBNull(var))
5
{
6
return "Null";
7
}
8
else if (var is int || var is double || var is int)
9
{
10
return var;
11
}
12
else
13
{
14
return "\"" + var + "\"";
15
}
16
}
Copied!

VB.NET Upgraded Code

1
Private Function ResultTxt(ByVal var As String) As String
2
'UPGRADE_WARNING: (2081) TypeName has a new behavior.'
3
'UPGRADE_WARNING: (1049) Use of Null/IsNull() detected.'
4
If Convert.IsDBNull(var) Then
5
Return "Null"
6
ElseIf var.GetType().Name = "Integer" Or var.GetType().Name = "Double" Or var.GetType().Name = "Long" Then
7
Return var
8
Else
9
Return """" & var & """"
10
End If
11
End Function
Copied!

1063 - Arrays in structure %1 may need to be initialized before they can be used

Description

In C#, fixed-size arrays in structures are not supported. Fixed-size arrays that are members of structures defined in COM interfaces will need to be initialized before they can be used.

Recommendations

    Call the Initialize function of the structure, right after the variable declaration.

VB6 Original Code

1
Private Type Structure2
2
Size As Integer
3
Numbers() As String
4
End Type
5
6
Private Type Structure1
7
name As String
8
str2 As Structure2
9
End Type
Copied!

C# Upgraded Code

1
[Serializable]
2
private struct Structure2
3
{
4
public short Size;
5
public string[] Numbers;
6
}
7
8
[Serializable]
9
private struct Structure1
10
{
11
public string name;
12
//UPGRADE_WARNING: (1063) Arrays in structure str2 may need to be initialized before they can be used.
13
public Structure2 str2;
14
public static Structure1 CreateInstance()
15
{
16
Structure1 result = new Structure1();
17
result.name = String.Empty;
18
return result;
19
}
20
}
Copied!

1068 - %1 of type %2 is being forced to %3

Description

The VBUC typing engine is able to infer the correct data type of undefined or Variant-type variables, and assign them the correct data type. In some scenarios, a variant-type variable is upgraded to a scalar value; this type of inference is done over the variable usage and context.

Recommendations

    There are no recommendations.

VB6 Original Code

1
Public Function Exists(col As Collection, Index As String) As Boolean
2
Dim o As Variant
3
On Error GoTo Error
4
o = col(Index)
5
Error:
6
MsgBox "Fail Test"
7
End Function
Copied!

C# Upgraded Code

1
internal static bool Exists(OrderedDictionary col, string Index)
2
{
3
object o = null;
4
try
5
{
6
//UPGRADE_WARNING: (1068) col() of type Variant is being forced to Scalar.
7
o = ReflectionHelper.GetPrimitiveValue(col[Index]);
8
}
9
catch
10
{
11
}
12
13
MessageBox.Show("Fail Test", AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
14
return false;
15
}
Copied!

VB.NET Upgraded Code

1
Public Function Exists(ByVal col As OrderedDictionary, ByVal Index As String) As Boolean
2
Dim o As Object
3
Try
4
'UPGRADE_WARNING: (1068) col() of type Variant is being forced to Scalar.'
5
o = ReflectionHelper.GetPrimitiveValue(col(Index))
6
Catch
7
End Try
8
9
MessageBox.Show("Fail Test", My.Application.Info.Title)
10
End Function
Copied!

1070 - Member access from a dynamic/late binding object will be resolved using the ReflectionHelper

Description

When the VBUC's mechanism for solving Late Binding cannot determine the type of a class, and the ReflectionHelper feature is enabled, the ReflectionHelper class will be used to attempt to correctly resolve the late binding instance at runtime.

Recommendations

    The ReflectionHelper class should be able to determine most cases of Late Binding at runtime.
    Manually modify the upgraded code to determine the correct base class.

VB6 Original Code

The original code uses a variant to allow any object to be passed, and have its Enabled property set to true. VB6's late binding will solve this.
1
Public Sub SetEnabled(ctrl As Variant)
2
ctrl.Enabled = True
3
End Sub
Copied!
In a case such as this where the VBUC cannot determine a base type for all items passed to the method, it will use the ReflectionHelper to solve the late binding issue at runtime, as seen in the following example.

C# Upgraded Code

1
public void SetEnabled(object ctrl)
2
{
3
ReflectionHelper.LetMember(ctrl, "Enabled", true);
4
}
Copied!

VB.NET Upgraded Code

1
Public Sub SetEnabled(ByVal ctrl As Object)
2
ReflectionHelper.LetMember(ctrl, "Enabled", True)
3
End Sub
Copied!

2050 - %1 Event %2.%3 was not upgraded

Description

The VBUC is able to map VB6 library members to .NET equivalents. These equivalents are chosen to provide maximum functional equivalence on the target platform. In particular scenarios, some class properties and events may not have a direct equivalent in .NET or may not have been mapped in the current release of the VBUC. The event handler is declared in the target source code but there are no equivalent events to associate the handler to.

Recommendations

    Use a more specialized/similar component to the original one, which provides the required events in the target platform.
    Create an explicit invocation to the event handler method in the given circumstances to simulate the event triggering.
    Associate the upgraded handler method to one or more .NET available events in case those events satisfy the code requirements and the original event behavior.
    Refactor the code to apply a different solution. This strategy makes sense especially when the concepts in .NET are very different from the VB6 ones. In these cases it is likely that the way to implement a particular process should be done with a different approach.

VB6 Original Code

1
Private Sub Text1_OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer)
2
'Make sure that the format is text.'
3
If Data.GetFormat(vbCFText) Then
4
'If it is text, enable dropping for the second Textbox.'
5
Text1.OLEDropMode = vbOLEDropManual
6
End If
7
End Sub
Copied!

C# Upgraded Code

1
//UPGRADE_WARNING: (2050) TextBox Event Text1.OLEDragOver was not upgraded.
2
private void Text1_OLEDragOver(DataObject Data, int Effect, int Button, int Shift, float X, float Y, int State)
3
{
4
//Make sure that the format is text.
5
//UPGRADE_ISSUE: (2064) ClipBoardConstants property ClipBoardConstants.vbCFText was not upgraded.
6
if (Data.GetFormat((short) UpgradeStubs.VBRUN_ClipBoardConstants.getvbCFText()))
7
{
8
//If it is text, enable dropping for the second Textbox.
9
//UPGRADE_ISSUE: (2070) Constant vbOLEDropManual was not upgraded.
10
//UPGRADE_ISSUE: (2064) TextBox property Text1.OLEDropMode was not upgraded.
11
Text1.setOLEDropMode(UpgradeStubs.VBRUN_OLEDropConstants.getvbOLEDropManual());
12
}
13
}
Copied!

C# Expected Code

In this case the sample code deals with manually handling Drag & Drop operations in a Visual Basic 6 application. As is clearly stated in that MSDN article we need to write custom code for the drag & drop operation. In this case, we replace the OLEDragOver event which no longer exists in .Net, and replaces it with the DragEnter event. Within this event, we add our drag & drop logic.
1
private void Text1_DragEnter(object sender, DragEventArgs e)
2
{
3
//Make sure that the format is text.
4
if (e.Data.GetDataPresent(DataFormats.Text))
5
{
6
//Allow drop
7
e.Effect = DragDropEffects.Copy;
8
}
9
else
10
{
11
e.Effect = DragDropEffects.None;
12
}
13
}
Copied!

VB.NET Upgraded Code

1
'UPGRADE_WARNING: (2050) TextBox Event Text1.OLEDragOver was not upgraded.'
2
Private Sub Text1_OLEDragOver(ByVal Data As DataObject, ByVal Effect As Integer, ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single, ByVal State As Integer)
3
'Make sure that the format is text.'
4
'UPGRADE_ISSUE: (2064) ClipBoardConstants property ClipBoardConstants.vbCFText was not upgraded.'
5
If Data.GetFormat(UpgradeSolution1Support.UpgradeStubs.VBRUN_ClipBoardConstants.getvbCFText()) Then
6
'If it is text, enable dropping for the second Textbox.'
7
'UPGRADE_ISSUE: (2070) Constant vbOLEDropManual was not upgraded.'
8
'UPGRADE_ISSUE: (2064) TextBox property Text1.OLEDropMode was not upgraded.'
9
Text1.setOLEDropMode(UpgradeSolution1Support.UpgradeStubs.VBRUN_OLEDropConstants.getvbOLEDropManual())
10
End If
11
End Sub
Copied!

VB.NET Expected Code

In this case, the sample code deals with manually handling Drag & Drop operations in a Visual Basic 6 application. As is clearly stated in that MSDN article we need to write custom code for the drag & drop operation. In this case, we replace the OLEDragOver event which no longer exists in .Net, and replaces it with the DragEnter event. Within this event, we add our drag & drop logic.
1
Private Sub Text1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Text1.DragEnter
2
'Make sure that the format is text.'
3
If (e.Data.GetDataPresent(DataFormats.Text)) Then
4
'Allow Drop'
5
e.Effect = DragDropEffects.Copy
6
Else
7
' Do not allow drop'
8
e.Effect = DragDropEffects.None
9
End If
10
End Sub
Copied!

2065 - %1 %2 %3.%4 has a new behavior

Description

During the upgrade process, some events can be mapped to .NET with minor behavior differences. If this EWI is displayed in a given project, the selected target event will not threaten the functional equivalence of the resulting code but can create small differences that may require some manual adjustments.

Recommendations

Each case will have to be evaluated individually, as the behavior differences may not be significant for every project. Some common properties with new behaviors include the following:
    System.Windows.Forms.Control.Controls collection, which is a hierarchical list of NamingContainers and is usually navigated recursively. It's important to remember that Child controls will not be in the parent's Controls collection.
    Likewise, System.Windows.Forms.ControlCollection.Count does not represent the same number in .NET as in VB6, as only direct descendants of the current control will be counted. Any child controls will be part of their respective parent's ControlCollection.

VB6 Original Code

1
Public Sub ShowPicture(ByVal myForm As Form)
2
MsgBox (myForm.Picture.Height)
3
End Sub
Copied!

C# Upgraded Code

1
internal static void ShowPicture(Form1 myForm)
2
{
3
//UPGRADE_WARNING: (2065) Form property myForm.Picture has a new behavior.
4
MessageBox.Show(myForm.BackgroundImage.Height.ToString(), AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
5
}
Copied!

VB.NET Upgraded Code

1
Public Sub ShowPicture(ByVal myForm As Form1)
2
'UPGRADE_WARNING: (2065) Form property myForm.Picture has a new behavior.'
3
MessageBox.Show(CStr(myForm.BackgroundImage.Height), My.Application.Info.Title)
4
End Sub
Copied!

2074 - %1 %2 %3.%4 was upgraded to %5.%6 which has a new behavior

Description

During the upgrade process, some class members and events can be mapped to a .NET equivalent with minor behavior differences. If this EWI is displayed in a given project, the selected source structure will not threaten the functional equivalence of the resulting code but can require some manual adjustments.

Recommendations

VB6 Original Code

1
Public Sub NewBehaviorParent(ByVal c As Control)
2
Dim b As Form
3
Set b = c.Parent
4
MsgBox c.Name & "'s parent is " & b.Name
5
End Sub
Copied!

C# Upgraded Code

1
public void NewBehaviorParent(Label c)
2
{
3
//UPGRADE_WARNING: (2074) Control property c.Parent was upgraded to c.FindForm which has a new behavior.
4
Form b = c.FindForm();
5
MessageBox.Show(c.Name + "'s parent is " + b.Name, AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
6
}
Copied!

VB.NET Upgraded Code

1
Public Sub NewBehaviorParent(ByVal c As Label)
2
'UPGRADE_WARNING: (2074) Control property c.Parent was upgraded to c.FindForm which has a new behavior.'
3
Dim b As Form = c.FindForm()