# ToDos

## 1035 - #If #EndIf block was not upgraded because the expression %1 did not evaluate to True or was not evaluated <a href="#id-1035" id="id-1035"></a>

#### Description

The #If #EndIf directives are evaluated by the VB6 AI Migrator preprocessing engine during the preliminary stage of the upgrade process. The current compiler-variable values are taken into consideration to figure out which blocks of code are active and which are inactive. The active blocks are upgraded to .NET, while the inactive ones are copied unchanged to the upgraded code and preceded by this EWI.

#### Recommendations

Often, conditional compilation directives might be missing and not all code paths will be expressed. Conditional compilation constants can be defined in three different ways in VB6:

| How To Set                    | Scope                                                   |
| ----------------------------- | ------------------------------------------------------- |
| Project Properties dialog box | Public to all modules in the project                    |
| Command line                  | Public to all modules in the project                    |
| #Const statement in code      | Available only in the module in which they are declared |

Knowing the scope of these constants can help when modifying the code to correct this EWI. If the inactive code is small and simple, it can safely be rewritten manually. However, if the conditionally compiled code is extensive, an extra migration might be required. Different values of the conditional constants can be used for all valid permutations. This will convert previously inactive blocks of code. The results can then be manually merged to get a fully converted code block.

In some cases, it might be possible to comment out the conditionally compiled code segments completely. This will only work if there are no conflicts and the original code can be upgraded without the conditional compilation directives.

{% hint style="danger" %}
In order to apply for this workaround, the original code should compile.
{% endhint %}

Some inactive blocks of code might no longer be in use. If this is the case, then those code segments can be removed. Special care should be taken when reviewing conditionally compiled code. Locally declared variables do not affect and are not used for the evaluation of conditional compilation directives.

#### VB6 Original Code

```visual-basic
#Const ShowMessage = -1 'True

Public Sub ConditionalCompilation()
   'ShowMessage is True'
   #If ShowMessage Then
      MsgBox "It will show this message!"
   #Else
      MsgBox "This text will not show!"
   #End If
End Sub

Public Sub ImproperConditionalCompilation()
   Dim show As Boolean
   Set show = True
   ' show is a local variable, and is not'
   ' used for conditional compilation'
   #If show Then
      MsgBox "This text will not show!"
   #Else
      'This message box is shown.'
      MsgBox "It will show this message!"
   #End If
End Sub
```

#### C# Upgraded Code

```csharp
internal static class Module1
{
   //True

   internal static void ConditionalCompilation()
   {
      //ShowMessage is True
#if ShowMessage
      MessageBox.Show("It will show this message!", AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
#else
      //UPGRADE_TODO: (1035) #If #EndIf block was not upgraded because the expression Else did not evaluate to True or was not evaluated.
      //        MsgBox "This text will not show!"
#endif
    }

    internal static void ImproperConditionalCompilation()
    {
      // show is a local variable, and is not
      // used for conditional compilation
#if show
      //UPGRADE_TODO: (1035) #If #EndIf block was not upgraded because the expression show did not evaluate to True or was not evaluated.
      //        MsgBox "This text will not show!"
#else
      //This message box is shown.
      MessageBox.Show("It will show this message!", AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
#endif
   }
}
```

#### VB.NET Upgraded Code

```vbnet
Module Module1
   #Const ShowMessage = -1 'True

   Public Sub ConditionalCompilation()
      'ShowMessage is True'
#If ShowMessage Then
      MessageBox.Show("It will show this message!", My.Application.Info.Title)
#Else
      'UPGRADE_TODO: (1035) #If #EndIf block was not upgraded because the expression Else did not evaluate to True or was not evaluated.'
      'MsgBox "This text will not show!"'
#End If
   End Sub

   Public Sub ImproperConditionalCompilation()
      ' show is a local variable, and is not'
      ' used for conditional compilation'
#If show Then
      'UPGRADE_TODO: (1035) #If #EndIf block was not upgraded because the expression show did not evaluate to True or was not evaluated.'
      'MsgBox "This text will not show!"'
#Else
      'This message box is shown.'
      MessageBox.Show("It will show this message!", My.Application.Info.Title)
#End If
   End Sub
End Module
```

## 1050 - Structure %1 may require marshalling attributes to be passed as an argument in this Declare statement <a href="#id-1050" id="id-1050"></a>

#### Description

In Visual Basic 6, user-defined types could be passed as an argument in a Declare statement for a Windows API. Actually, we have a feature called PInvoke (Platform Invocation Service) that allows calls to native code and interact with .NET unmanaged code.

In Visual Basic .NET, a structure (user-defined type) passed as an argument in a Declare statement may require additional marshalling attributes in order to be passed correctly to the external function or subroutine. In particular, arrays and fixed-length strings may not function as expected without these attributes.

As mentioned before, we use the PInvoke feature; in this case, the declared statement will be commented and a new struct will be created using this feature in another file.

**To see more information:** [PInvoke feature](/vbuc/features.md#windows-api-to-pinvoke)

#### Recommendations

Add an Imports statement to reference the System.Runtime.InteropServices namespace and then modify the structure and the string declaration to include marshalling attributes.

#### VB6 Original Code

```visual-basic
Private Type MyStructure
   Name As String
   size As Integer
End Type

Declare Function FunctionName Lib "MyLibrary.DLL" (ByVal rs1 As MyStructure) As Long
```

#### C# Upgraded Code

*Module1.cs*

```csharp
//UPGRADE_NOTE: (2041) The following line was commented.
////UPGRADE_TODO: (1050) Structure MyStructure may require marshalling attributes to be passed as an argument in this Declare statement.
//[DllImport("MyLibrary.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
//extern public static int FunctionName(UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.MyStructure rs1);
```

*UnsafeMethods\Structures.cs*

```csharp
public struct MyStructure
{
   public string Name;
   public short size;
   private static void InitStruct(ref MyStructure result, bool init)
   {
      if (init)
      {
         result.Name = String.Empty;
      }
   }
   public static MyStructure CreateInstance()
   {
      MyStructure result = new MyStructure();
      InitStruct(ref result, true);
      return result;
   }
   public MyStructure Clone()
   {
      MyStructure result = this;
      InitStruct(ref result, false);
      return result;
   }
}
```

#### C# Expected Code

*Module1.cs*

```csharp
//UPGRADE_NOTE: (2041) The following line was commented.
////UPGRADE_TODO: (1050) Structure MyStructure may require marshalling attributes to be passed as an argument in this Declare statement.
//[DllImport("MyLibrary.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
//extern public static int FunctionName(UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.MyStructure rs1);
```

*UnsafeMethods\Structures.cs*

```csharp
public struct MyStructure
{
   [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 256)]
   public string Name;
   [MarshalAs(UnmanagedType.I4)]
   public short size;
   private static void InitStruct(ref MyStructure result, bool init)
   {
      if (init)
      {
         result.Name = String.Empty;
      }
   }
   public static MyStructure CreateInstance()
   {
      MyStructure result = new MyStructure();
      InitStruct(ref result, true);
      return result;
   }
   public MyStructure Clone()
   {
      MyStructure result = this;
      InitStruct(ref result, false);
      return result;
   }
}
```

#### VB.NET Upgraded Code

*Module1.vb*

```vbnet
'UPGRADE_NOTE: (2041) The following line was commented.'
'UPGRADE_TODO: (1050) Structure MyStructure may require marshalling attributes to be passed as an argument in this Declare statement.'
'Declare Function FunctionName Lib "MyLibrary" (ByVal rs1 As UpgradeSolution1Support.UnsafeNative.Structures.MyStructure) As Integer'
```

*UnsafeMethods\Structures.vb*

```vbnet
Public Structure MyStructure
   Dim Name As String
   Dim size As Short
   Private Shared Sub InitStruct(ByRef result As MyStructure, ByVal init As Boolean)
      If init Then
         result.Name = String.Empty
      End If
   End Sub
   Public Shared Function CreateInstance() As MyStructure
      Dim result As New MyStructure()
      InitStruct(result, True)
      Return result
   End Function
   Public Function Clone() As MyStructure
      Dim result As MyStructure = Me
      InitStruct(result, False)
      Return result
   End Function
End Structure
```

#### VB.NET Expected Code

*Module1.vb*

```vbnet
'UPGRADE_NOTE: (2041) The following line was commented.'
'UPGRADE_TODO: (1050) Structure MyStructure may require marshalling attributes to be passed as an argument in this Declare statement.'
'Declare Function FunctionName Lib "MyLibrary" (ByVal rs1 As UpgradeSolution1Support.UnsafeNative.Structures.MyStructure) As Integer'
```

*UnsafeMethods\Structures.vb*

```vbnet
Public Structure MyStructure
   <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)>
   Dim Name As String
   <MarshalAs(UnmanagedType.I4)>
   Dim size As Short
   Private Shared Sub InitStruct(ByRef result As MyStructure, ByVal init As Boolean)
      If init Then
         result.Name = String.Empty
      End If
   End Sub
   Public Shared Function CreateInstance() As MyStructure
      Dim result As New MyStructure()
      InitStruct(result, True)
      Return result
   End Function
   Public Function Clone() As MyStructure
      Dim result As MyStructure = Me
      InitStruct(result, False)
      Return result
   End Function
End Structure
```

## 1059 - Code was upgraded to use %1 which may not have the same behavior <a href="#id-1059" id="id-1059"></a>

#### Description

This EWI appears when a Visual Basic method call is changed to a .NET counterpart that may not have the same behavior as the original.

#### Recommendations

* In most cases, the .NET equivalents provide equivalent functionality, but there can be some cases for which its functionality differs. Most commonly VB6 performed a lot of validations and auto coercions. Unfortunately, there is such a wide variety of cases that might cause this EWI that it would be prohibitive to list them all with possible resolutions. It is, however, important to note that oftentimes these differences can depend on the parameters passed to the methods. Thus choosing a different signature of the same method might provide the desired functionality.
* Therefore, it is recommended that the migration consultant research the target and source methods to achieve the desired functionality.

#### VB6 Original Code

```visual-basic
Attribute VB_Name = "Module1"
Public Function CoercionArrayToString(ByRef ByteArray() As Byte) As String
   CoercionArrayToString = ByteArray
End Function

Public Function CoercionStringToArray(ByVal ByteText As String) As Byte()
   CoercionStringToArray = ByteText
End Function
```

#### C# Upgraded Code

```csharp
internal static string CoercionArrayToString(byte[] ByteArray)
{
   //UPGRADE_WARNING: (1059) Code was upgraded to use UpgradeHelpers.Helpers.StringsHelper.ByteArrayToString() which may not have the same behavior.
   return StringsHelper.ByteArrayToString(ByteArray);
}

internal static byte[] CoercionStringToArray(string ByteText)
{
   //UPGRADE_WARNING: (1059) Code was upgraded to use System.Text.UnicodeEncoding.Unicode.GetBytes() which may not have the same behavior.
   return UnicodeEncoding.Unicode.GetBytes(ByteText);
}
```

#### VB.NET Upgraded Code

```vbnet
Public Function CoercionArrayToString(ByVal ByteArray() As Byte) As String
   'UPGRADE_WARNING: (1059) Code was upgraded to use UpgradeHelpers.Helpers.StringsHelper.ByteArrayToString() which may not have the same behavior.'
   Return StringsHelper.ByteArrayToString(ByteArray)
End Function

Public Function CoercionStringToArray(ByVal ByteText As String) As Byte()
   'UPGRADE_WARNING: (1059) Code was upgraded to use System.Text.UnicodeEncoding.Unicode.GetBytes() which may not have the same behavior.'
   Return UnicodeEncoding.Unicode.GetBytes(ByteText)
End Function
```

## 1065 - Error handling statement (%1) could not be converted <a href="#id-1065" id="id-1065"></a>

#### Description

This EWI is generated when an error-handling statement is too complex or if it is a pattern that is not supported by the VB6 AI Migrator.

#### Recommendations

* Most occurrences of this EWI will require manual changes to the source code to fix the issue. However, most cases of an error label that is globally called within a function can be replaced by a single try-catch statement with the addition of return statements.
* The error handling is associated with the *Error Handling* upgrade option in the VB6 AI Migrator Tool. You can change it to generate different code.

**See also:** [Error Handling Upgrade Option](/vbuc/generated-code.md#error-handling-1)

#### VB6 Original Code

```visual-basic
Public Function ErrorHandlingStatement() As String
   Dim ObjD As Integer
   On Error GoTo LabelErr
LabelStart:
   ObjD = ErrRaisableSub
LabelExit:
   Exit Function
LabelErr:
   If ObjD = 1 Then
      Resume LabelStart
   Else
      Resume LabelExit
   End If
End Function
```

#### C# Upgraded Code

```csharp
public string ErrorHandlingStatement()
{
   int ErrRaisableSub = 0;
   int ObjD = 0;
   try
   {
      LabelStart:
      ObjD = ErrRaisableSub;
      LabelExit:;}
   catch
   {
      if (ObjD == 1)
      {
         //UPGRADE_TODO: (1065) Error handling statement (LabelStart) could not be converted.
         UpgradeHelpers.Helpers.NotUpgradedHelper.NotifyNotUpgradedElement("Resume Label (LabelStart)");
      }
      else
      {
         //UPGRADE_TODO: (1065) Error handling statement (LabelExit) could not be converted.
         UpgradeHelpers.Helpers.NotUpgradedHelper.NotifyNotUpgradedElement("Resume Label (LabelExit)");
      }
   }
   return "";
}
```

#### VB.NET Upgraded Code

```vbnet
Public Function ErrorHandlingStatement() As String
   Dim ErrRaisableSub, ObjD As Integer
   Try
LabelStart:
      ObjD = ErrRaisableSub
LabelExit:
   Catch
      If ObjD = 1 Then
         'UPGRADE_TODO: (1065) Error handling statement (LabelStart) could not be converted.'
         UpgradeHelpers.Helpers.NotUpgradedHelper.NotifyNotUpgradedElement("Resume Label (LabelStart)")
      Else
         'UPGRADE_TODO: (1065) Error handling statement (LabelExit) could not be converted.'
         UpgradeHelpers.Helpers.NotUpgradedHelper.NotifyNotUpgradedElement("Resume Label (LabelExit)")
      End If
   End Try
End Function
```

## 1067 - Member %2 is not defined in type %3 <a href="#id-1067" id="id-1067"></a>

#### Description

This EWI appears when an object cannot be typed correctly or a particular method could not be found in the class. This usually occurs in late binding scenarios. In some cases, the VB6 AI Migrator will still be unable to map the reference correctly due to late binding scenarios where multiple types are sent as parameters.

**See also:** [Late Binding Resolution](/vbuc/generated-code.md#late-binding-resolution)

#### VB6 Original Code

```visual-basic
Public Sub CreateObjectExample()
   Dim PluginObj
   PluginObj = CreateObject("PluginNamespace.Plugin")
   PluginObj.Property = 0
   PluginObj.Func ("A")
   PluginObj.Action (1)
End Sub
```

#### C# Upgraded Code

```csharp
public void CreateObjectExample()
{
   //UPGRADE_WARNING: (7008) The ProgId could not be found on computer where this application was migrated.
   //UPGRADE_WARNING: (1068) CreateObject() of type Plugin is being forced to Scalar.
   object PluginObj = ReflectionHelper.GetPrimitiveValue(Activator.CreateInstance(Type.GetTypeFromProgID("PluginNamespace.Plugin")));
   //UPGRADE_TODO: (1067) Member Property is not defined in type Variant.
   PluginObj.Property = 0;
   //UPGRADE_TODO: (1067) Member Func is not defined in type Variant.
   PluginObj.Func("A");
   //UPGRADE_TODO: (1067) Member Action is not defined in type Variant.
   PluginObj.Action(1);
}
```

#### VB.NET Upgraded Code

```vbnet
Public Sub CreateObjectExample()
   'UPGRADE_WARNING: (7008) The ProgId could not be found on computer where this application was migrated.'
   'UPGRADE_WARNING: (1068) CreateObject() of type Plugin is being forced to Scalar.'
   Dim PluginObj As Object = ReflectionHelper.GetPrimitiveValue(Activator.CreateInstance(Type.GetTypeFromProgID("PluginNamespace.Plugin")))
   'UPGRADE_TODO: (1067) Member Property is not defined in type Variant.'
   PluginObj.Property = 0
   'UPGRADE_TODO: (1067) Member Func is not defined in type Variant.'
   PluginObj.Func("A")
   'UPGRADE_TODO: (1067) Member Action is not defined in type Variant.'
   PluginObj.Action(1)
End Sub
```

## 1069 - Error handling statement (%1) was converted to a pattern that might have a different behavior <a href="#id-1069" id="id-1069"></a>

#### Description

This usually occurs when a Resume Next Error Handling Pattern appears. It is a warning because functional equivalence could not be accomplished in this scenario.

#### Recommendations

* The Resume Next error handling pattern resumes execution of the next statement after an error. In the case of structured error handling, the resulting behavior is more similar to an On Error GoTo statement, where the catch statement serves as the GoTo label. For this reason, the replacement done by the VB6 AI Migrator might not be the exact functional equivalent of the original code. In cases where the code is related, meaning if one call fails subsequent calls are likely to fail, then leaving a single try-catch statement could work. Since an error at any point of the process would merely be replicated in the subsequent.
* In other cases, the error pattern of Resume Next is necessary when the code statements are fairly independent (a failure in one statement does not affect the error condition of a subsequent call). In order to ensure functional equivalence, it's necessary to add a try-catch (with an empty clause) to each line that can throw an exception. In these cases the main try-catch (generated by the VB6 AI Migrator) is less effective and should be removed.
* The error handling is associated with the *Error Handling* upgrade option in the VB6 AI Migrator Tool. You can change it to generate a different code.

**See also:** [Error Handling Upgrade Option](/vbuc/generated-code.md#error-handling-1)

#### VB6 Original Code

```visual-basic
Public Function ComplexErrorPattern() As Integer
   F1 (1)
   On Error Resume Next

   Dim I As Integer
   I = 0
   I = F2(1)
   If I <> 0 Then
      I = F4(80)
   Else
      I = F3(50)
   End If
Exit_Label:
   ComplexErrorPattern = I
   Exit Function
End Function
```

#### C# Upgraded Code

```csharp
public int ComplexErrorPattern()
{
   int[] F2 = null;
   int[] F4 = null;
   object[] F1 = null;
   int[] F3 = null;
   object tempAuxVar = F1[1];
   //UPGRADE_TODO: (1069) Error handling statement (On Error Resume Next) was converted to a pattern that might have a different behavior.
   try
   {
      int I = 0;
      I = F2[1];
      if (I != 0)
      {
         I = F4[80];
      }
      else
      {
         I = F3[50];
      }
      return I;
   }
   catch (Exception exc)
   {
      NotUpgradedHelper.NotifyNotUpgradedElement("Resume in On-Error-Resume-Next Block");
   }
   return 0;
}
```

#### VB.NET Upgraded Code

```vbnet
Public Function ComplexErrorPattern() As Integer
   Dim F2() As Integer, F4() As Integer
   Dim F1() As Object
   Dim F3() As Integer
   Dim tempAuxVar As Object = F1(1)
   'UPGRADE_TODO: (1069) Error handling statement (On Error Resume Next) was converted to a pattern that might have a different behavior.'
   Try
      Dim I As Integer = 0
      I = F2(1)
      If I <> 0 Then
         I = F4(80)
      Else
         I = F3(50)
      End If
      Return I
   Catch exc As Exception
      NotUpgradedHelper.NotifyNotUpgradedElement("Resume in On-Error-Resume-Next Block")
   End Try
End Function
```

## 2018 - Remove the next line of code to stop form from automatically showing <a href="#id-2018" id="id-2018"></a>

#### Description

VB6 AI Migrator converts MDI forms to regular .NET forms but also applies specific conversion rules in order to emulate exactly the same behavior as in VB6. If that behavior is no longer wanted, then just remove the tagged comment and the line of code that calls the Show method of the form.

{% hint style="info" %}
This EWI will appear in the designer file.
{% endhint %}

#### Recommendations

* If the MDI form in the VB6 project had its AutoShowChildren property set to True, to simulate the VB6 behavior, VB6 AI Migrator needs to automatically show the form whenever it is loaded.

#### VB6 Original Code

*MDIForm1.frm*

```visual-basic
Private Sub MDIForm_Load()
   Form1Child.Show
End Sub
```

#### C# Upgraded Code

*Form1Child.Designer.cs*

```csharp
partial class Form1Child
{
   ...
   public static Form1Child CreateInstance()
   {
      Form1Child theInstance = new Form1Child();
      //The MDI form in the VB6 project had its
      //AutoShowChildren property set to True
      //To simulate the VB6 behavior, we need to
      //automatically Show the form whenever it
      //is loaded.  If you do not want this behavior
      //then delete the following line of code
      //UPGRADE_TODO: (2018) Remove the next line of code to stop form from automatically showing.
      theInstance.Show();
      return theInstance;
   }
   ...
   void ReLoadForm(bool addEvents)
   {
      //This form is an MDI child.
      //This code simulates the VB6 
      // functionality of automatically
      // loading and showing an MDI
      // child's parent.
      this.MdiParent = Project1.MDIForm1.DefInstance;
      Project1.MDIForm1.DefInstance.Show();
   }
}
```

#### VB.NET Upgraded Code

*Form1Child.Designer.vb*

```vbnet
Partial Class Form1Child
   Public Shared Function CreateInstance() As Form1Child
      Dim theInstance As New Form1Child()
      'The MDI form in the VB6 project had its'
      'AutoShowChildren property set to True'
      'To simulate the VB6 behavior, we need to'
      'automatically Show the form whenever it'
      'is loaded.  If you do not want this behavior'
      'then delete the following line of code'
      'UPGRADE_TODO: (2018) Remove the next line of code to stop form from automatically showing.'
      theInstance.Show()
      Return theInstance
   End Function
   ...
   Sub ReLoadForm(ByVal addEvents As Boolean)
      'This form is an MDI child.'
      'This code simulates the VB6 '
      ' functionality of automatically'
      ' loading and showing an MDI'
      ' childs parent.'
      Me.MdiParent = Project1.MDIForm1.DefInstance
      Project1.MDIForm1.DefInstance.Show()
      ...
   End Sub
End Class
```

## 2045 - Only TrueType and OpenType fonts are supported in Windows Forms <a href="#id-2045" id="id-2045"></a>

#### VB6 Original Code

```visual-basic
Private Sub Form_Load()
   Text1.FontName = "MS Sans Serif"
   cboBundleName.FontName = "MS Sans Serif"
End Sub
```

#### C# Upgraded Code

```csharp
private void Form_Load()
{
   //UPGRADE_WARNING: (2045) Only TrueType and OpenType fonts are supported in Windows Forms.
   Text1.Font = Text1.Font.Change(name:"MS Sans Serif");
   //UPGRADE_WARNING: (2045) Only TrueType and OpenType fonts are supported in Windows Forms.
   cboBundleName.Font = cboBundleName.Font.Change(name:"MS Sans Serif");
}
```

#### VB.NET Upgraded COde

```vbnet
Private Sub Form_Load()
   'UPGRADE_WARNING: (2045) Only TrueType and OpenType fonts are supported in Windows Forms.'
   Text1.Font = Text1.Font.Change(name:="MS Sans Serif")
   'UPGRADE_WARNING: (2045) Only TrueType and OpenType fonts are supported in Windows Forms.'
   cboBundleName.Font = cboBundleName.Font.Change(name:="MS Sans Serif")
End Sub
```

## 7010 - The connection string must be verified to fullfill the .NET data provider connection string requirements <a href="#id-7010" id="id-7010"></a>

#### Description

In most cases, the conversion of ADO, RDO, or DAO to ADO.NET will require a manual modification of the connection string.

#### Recommendations

* ADO.NET uses different parameters to connect to the database. The easiest way to know the appropriate connection string in the .NET environment is to use the "Data Connections" tool, which can be found in the "Server Explorer" tab of the .NET IDE, to create a new connection to the database and get the complete connection string from there.
* This EWI is associated with the ADODB Upgraded Option. You can change it to generate a different code.

**See also:** [ADODB to ADO.NET](/vbuc/generated-code.md#adodb-to-ado-net)

#### VB6 Original Code

```visual-basic
Public Sub connect()
   'Instantiate the connection'
   Set cnConexion = New Connection

   'Configure the connection string'
   strConex = "DRIVER=SQL Server;Database=NorthwindSQL;APP=Microsoft Data Access Components;SERVER=.\SQLEXPRESS"

   'Set the connection string of the Connection object'
   cnConexion.ConnectionString = strConex

   'Open the connection'
   cnConexion.Open
End Sub
```

#### C# Upgraded Code

```csharp
internal static void connect()
{
   //Instantiate the connection
   DbConnection cnConexion = UpgradeHelpers.DB.AdoFactoryManager.GetFactory().CreateConnection();

   //Configure the connection string
   string strConex = "DRIVER=SQL Server;Database=NorthwindSQL;APP=Microsoft Data Access Components;SERVER=.\\SQLEXPRESS";

   //Set the connection string of the Connection object
   cnConexion.ConnectionString = strConex;

   //Open the connection
   //UPGRADE_TODO: (7010) The connection string must be verified to fullfill the .NET data provider connection string requirements.
   cnConexion.Open();
}
```

#### VB.NET Upgraded Code

```vbnet
Public Sub connect()
   'Instantiate the connection'
   Dim cnConexion As DbConnection = UpgradeHelpers.DB.AdoFactoryManager.GetFactory().CreateConnection()

   'Configure the connection string'
   Dim strConex As String = "DRIVER=SQL Server;Database=NorthwindSQL;APP=Microsoft Data Access Components;SERVER=.\SQLEXPRESS"

   'Set the connection string of the Connection object'
   cnConexion.ConnectionString = strConex

   'Open the connection'
   'UPGRADE_TODO: (7010) The connection string must be verified to fullfill the .NET data provider connection string requirements.'
   cnConexion.Open()
End Sub
```

## 7016 - This property was auto-generated because it is used in WriteProperties but does not exist. <a href="#id-7016" id="id-7016"></a>

#### Description

Visual Basic 6 allows the user to add design-time properties to user controls by adding them in the WriteProperties event of the UserControl class, even though the properties are not defined in the UserControl.  The following example defines such a UserControl.

#### VB6 Original Code

```visual-basic
Begin VB.UserControl MyUserControl 
   ClientHeight    =   570
   ClientLeft      =   0
   ClientTop       =   0
   ClientWidth     =   2265
   ScaleHeight     =   570
   ScaleWidth      =   2265
   Begin VB.ComboBox Combo1 
      Height          =   315
      Left            =   120
      TabIndex        =   0
      Text            =   "Combo1"
      Top             =   120
      Width           =   2055
   End
End
Attribute VB_Name = "MyUserControl"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Private active as Boolean

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    active = PropBag.ReadProperty("IsActive", False)
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    Call PropBag.WriteProperty("IsActive", active)
End Sub
```

When this type of control is added to a form, the form's designer code will look like this:

```vba
Begin Project1.Chkx Chkx1 
   Height          =   855
   Left            =   120
   TabIndex        =   0
   Top             =   120
   Width           =   1815
   _ExtentX        =   3201
   _ExtentY        =   1508
   IsActive        =   -1  'True
End
```

Since the UserControl does not contain an IsActive property, the VB6 AI Migrator will auto-generate one to provide a single place to fix this issue.

#### C# generated code

```csharp
//UPGRADE_ISSUE: (2068) PropertyBag object was not upgraded. More Information: https://docs.mobilize.net/vbuc/ewis#2068
//UPGRADE_WARNING: (6002) UserControl Event ReadProperties is not supported. More Information: https://docs.mobilize.net/vbuc/ewis#6002
private void UserControl_ReadProperties(ref UpgradeStubs.PropertyBag PropBag)
{
	//UPGRADE_ISSUE: (2064) PropertyBag method PropBag.ReadProperty was not upgraded. More Information: https://docs.mobilize.net/vbuc/ewis#2064
	//UPGRADE_WARNING: (1068) PropBag.ReadProperty() of type Variant is being forced to bool. More Information: https://docs.mobilize.net/vbuc/ewis#1068
	active = Convert.ToBoolean(PropBag.ReadProperty("IsActive", false));
}

//UPGRADE_ISSUE: (2068) PropertyBag object was not upgraded. More Information: https://docs.mobilize.net/vbuc/ewis#2068
//UPGRADE_WARNING: (6002) UserControl Event WriteProperties is not supported. More Information: https://docs.mobilize.net/vbuc/ewis#6002
private void UserControl_WriteProperties(UpgradeStubs.PropertyBag PropBag)
{
	//UPGRADE_ISSUE: (2064) PropertyBag method PropBag.WriteProperty was not upgraded. More Information: https://docs.mobilize.net/vbuc/ewis#2064
	PropBag.WriteProperty("IsActive", active, null);
}

//UPGRADE_TODO: (7016) This property was auto-generated because it is used in WriteProperties but does not exist. More Information: https://docs.mobilize.net/vbuc/ewis#7016
private object _IsActive = null;
[Browsable(true)]
public object IsActive
{
	get
	{
		return _IsActive;
	}
	set
	{
		_IsActive = value;
	}
}
```

#### Recommendations

This code will provide the missing property at design time, but will need to be manually changed to provide the same functionality as the VB6 program.  By using the contents of ReadProperties and WriteProperties, it should be possible to manually change the getter and setter of the new property to achieve functional equivalence.

## How to prevent the application from exiting immediately after starting

#### Basic Scenario

The basic scenario is the invocation of the main form of the application from the Main sub. This is described here.

#### VB6 Application

We have a simple application with a main module which contains the main sub, and a main form that is displayed in the main sub.

![Startup Project](/files/-MEi3de4wsFc2Z0d51qs)

This is the code for the main module:

```visual-basic
Public Sub Main()
   MainForm.Show
   MsgBox "This message should be displayed first"
End Sub
```

As mentioned before, this application will start the execution on the main sub, display the main form and exit the main sub, keeping the main form open. The application will exit as soon as the main form is closed.

#### Upgraded Application

The VB6 AI Migrator tool generates lines that are equivalent to the lines in the original application, it also generates an [EWI](/vbuc/generated-code.md#ewis) informing the user that the "[Application will terminate when Sub Main() finishes](/vbuc/ewis.md#1047-application-will-terminate-when-sub-main-finishes)".

```csharp
//UPGRADE_WARNING: (1047) Application will terminate when Sub Main() finishes.
[STAThread]
public static void Main()
{
   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);
   Application.Run(MainForm.DefInstance);
   MessageBox.Show("This message should be displayed first", AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
}
```

If we execute this code, the main form window will be displayed and the main sub will not be executed until the main form is closed. To fix this behavior, you need to change the order in the VB6 application, placing *form.show* at the end of the main sub.

*VB6 Code*

```visual-basic
Public Sub Main()
   MsgBox "This message should be displayed first"
   MainForm.Show
End Sub
```

*CS Upgraded Code*

```csharp
[STAThread]
public static void Main()
{
   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);
   MessageBox.Show("This message should be displayed first", AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
   Application.Run(MainForm.DefInstance);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gapvelocity.ai/vbuc/ewis/todos.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
