# VB6 AI Migrator Features

## Command-Line Interface

The VB6 AI Migrator provides a command-line interface that allows you to upgrade your code via command line rather than using the GUI.

The command to create an upgrade solution and perform the upgrade process is:

***vbuccmd \<sourcePath> \<solutionName(without extension)> \[options\*]***

If you wish to upgrade an existing solution file, use the following command:

***vbuccmd \<solutionfile> \[options\*]***

Options detail:

| Option                                                                   | Description                                                                                                                                                                                                                                                                                                                                                                                                                               |            |                                                         |
| ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------- |
| **/?**                                                                   | Show the usage of the VbucCmd.                                                                                                                                                                                                                                                                                                                                                                                                            |            |                                                         |
| **/license**                                                             | Display the license information.                                                                                                                                                                                                                                                                                                                                                                                                          |            |                                                         |
| **/out \<outputPath>**                                                   | <p>Specify the output directory.<br>Default: \<sourcePath>\UpgradeOutput</p>                                                                                                                                                                                                                                                                                                                                                              |            |                                                         |
| **/target {vb\|cs}**                                                     | <p>Specify the target language.<br>Default: vb</p>                                                                                                                                                                                                                                                                                                                                                                                        |            |                                                         |
| **/upgradeoption \<file>**                                               | <p>Upgrade Option file to use.<br>Values: Standard                                                                                                                                                                                                                                                                                                                                                                                        | MoreDotNet | MoreInterop<br>Or a new option created by the user.</p> |
| **/vsversion \<version>**                                                | <p>Choose the Visual Studio Version for output.<br>(2017                                                                                                                                                                                                                                                                                                                                                                                  | 2019       | 2022)</p>                                               |
| **/netframework \<NET-version>**                                         | <p><strong>\<NET-version></strong> values:<br>4.7 - available for VS2017 onwards<br>4.7.2 - available for VS2019 onwards<br>4.8 - available for VS2019 onwards<br>net8 - available for VS2022<br>net9 - available for VS2022<br>net10 - available for VS2022</p>                                                                                                                                                                          |            |                                                         |
| **/folder \<folder>**                                                    | Choose to preprocess/upgrade only one subfolder (it has to be relative to the solution source path).                                                                                                                                                                                                                                                                                                                                      |            |                                                         |
| **/includeNeeded**                                                       | Include all needed\* projects in the preprocess phase.                                                                                                                                                                                                                                                                                                                                                                                    |            |                                                         |
| **/ignoreWarnings**                                                      | Don't update warnings when loading a solution.                                                                                                                                                                                                                                                                                                                                                                                            |            |                                                         |
| **/phase \<phaseId>**                                                    | <p>Execute only the indicated phase.<br>(Default: Preprocess and upgrade)<br><br><strong>\<phaseId></strong> values:<br><em>solution</em> - Only create a solution file. Not valid for case #2 above.<br><em>preprocess</em> - Only preprocess projects and create analysis information.<br><em>upgrade</em> - Only upgrade phase using existing preprocess information.<br><em>assessment</em> - Generate the assessment report XML.</p> |            |                                                         |
| <p><strong>Typing options</strong><br>(only one option can be used)</p>  | <p><em>/typer</em> - Use full typing for object and variant members.<br><em>/noTyper</em> - Don't use typing for object and variant members.<br><em>/localTyper</em> - Use local typing for object and variant members.</p>                                                                                                                                                                                                               |            |                                                         |
| <p><strong>Helpers options</strong><br>(only one option can be used)</p> | <p><em>/binaryHelpers</em> - Use of binary helpers (default for vb.net language).<br><em>/sourceCodeHelpers</em> - Use of source code helpers (default for c# language).<br><em>/nugetsHelpers \[-version=9.x.x]</em> - Use helpers as nugets (for VS 2019 onwards), optionally reads the nugets version.</p>                                                                                                                             |            |                                                         |
| **/parallel \<degree>**                                                  | <p>Sets the number of projects to be upgraded in parallel.<br>If not specified uses a value calculated based on the computer's resources.</p>                                                                                                                                                                                                                                                                                             |            |                                                         |
| **/log \<level>**                                                        | <p>Sets the verbosity of the output log.<br><br><strong>\<level></strong> values:<br><em>error</em> - only errors are logged.<br><em>warning</em> - Only warnings and errors are logged.<br><em>info</em> - Basic output, including errors and warnings.<br><em>debug</em> - Detailed output, including errors and warnings.<br>If not specified, the default value is <em>debug</em>.</p>                                                |            |                                                         |

\*The needed projects are those that reference or are referenced by one of the projects included in the upgrade. If the needed project is not in the upgrade solution, it will not be included.

### Examples

Upgrade all the VB6 projects that are contained in "C:\Source Code\\" to C# and leave the output in "C:\Source Code\OutputPath":

***vbuccmd "C:\Source Code" MySolutionFilename /out ./OutputPath /target cs***

Perform upgrade on all the projects specified in an upgrade solution file:

***vbuccmd SolutionFilename.VBCSln***

## Assessment Process

VB6 AI Migrator (VB6) will switch to assessment mode once the current license is expired. This mode allows the user to perform the following actions:

* Create upgrade solutions to solve pre-migration issues i.e. missing references or files.
* Create the assessment report to quantify the efforts required for the migration task.

VB6 AI Migrator will be installed by default in assessment mode if a valid license file is not provided after the installation process. Once VB6 AI Migrator is activated, the assessment mode features will be present in the full version.

### How to run the Assessment

#### Before starting

Before running the Assessment, it's necessary to follow these steps to have a successful analysis:

> See [Create a VBUC Solution](/vbuc/get-started.md#create-a-vbuc-solution) and [Resolve References](/vbuc/get-started.md#resolve-references)

#### Running VB6 AI Migrator in Assessment Mode

First, select the Assessment option from the Tools menu.

![VB6 AI Migrator Assessment option](/files/-Ma-fpeytdesMTEgKcVB)

Once the option is selected, the Assessment window will appear.

![VB6 AI Migrator Assessment Window](/files/CRwsiiL9CYb4kVFozrAl)

Run the Assessment, and it will analyze your VB6 project. Once the analysis is done, you can review the result in a browser by pressing the "Show Results" button. Also, there is a folder called Assessment located in the Output Path. In the next section, you can see the report files.

### Assessment report

* **Upgrade Solution (\*.VBCSln)**
  * Used to solve:
    * Internal and external References
    * Project dependencies
* **LOC Report.xml**
  * Source files per project
  * Recommended upgrade order
  * Lines of code (code, comments, spaces, design lines)
    * Per Project
    * Detail per file
* **AssessmentReport.xml**
  * Used by Mobilize personnel for estimations.
  * Information provided:
    * Third-party controls:
      * Used methods and properties
      * Events
    * Data Access components
    * COM+ summary and members
    * Intrinsic components
    * Windows API calls
    * Much more

## Dependency Analyzer

### How to run the Dependency Analyzer

The Dependency Analyzer enables the user to work with the solution and project dependencies. First check the output file is the correct one.

![Dependency Analyzer tool](/files/w0nsr7ee8iI8MRP8kvJO)

The user has to select the projects that want to analyze, once the projects are selected press the "Analyze" button. It shows all the dependencies from the corresponding projects, as shown below. In addition, by clicking the "Show Table" button it generates a .csv file with all this information.

![Dependency Analyzer Result](/files/-MILx2VpD-6DIPktx4bo)

## Typing

This section describes the Typing mechanism used by the VB6 AI Migrator to determine the type of certain elements.

### VB6 AI Migrator Type Inference

In Visual Basic 6.0, it is very common to use variables without an explicit declaration.

The Visual Basic Upgrade Companion generates all the explicit, fully-typed declarations for these variables avoiding the usage of generic data types (i.e. Object). The VB6 AI Migrator's type inference engine determines the most appropriate data types for variables, parameters, fields, and return values.

The Visual Basic Upgrade Companion is able to solve variable, method, and inter-project scope typing issues. The resulting source code boasts full typed variable declarations and explicit castings (if necessary) for all the variables, based on their usage and programmatic behavior.

The typing issues are simple to fix on a small scale, but it is complexity raises when combined with late binding and unusual programming practices. The manual changes required to obtain a functionally equivalent code will proportionally grow with the migration project size.

The Visual Basic Upgrade Companion will shorten the manual changes stage by providing pure, high quality, and fully typed .NET source code, allowing the entire migration project to be executed in less time than expected, reducing the overall costs and assuring the highest ROI.

The following VB6 source code sample contains three non-typed and one fixed-length string variable being used and assigned in a particular way.

**Original VB6 Source Code**

```php
Private Sub typeInference()
  Dim var1
  Dim var2
  Dim var3
  Dim var4 As String * 50
  var4 = App.Path
  var1 = ArgTypeInference(var2, var3, var4, Len(var4))
End Sub

Public Function ArgTypeInference(ByVal arg1 As Integer, ByVal arg2 As String, ByVal arg3 As String, ByVal arg4 As Integer)
  MsgBox arg1
  MsgBox arg2
  MsgBox arg3
  MsgBox arg4
  ArgTypeInference = 1
End Function
```

Due to its advanced type inference mechanism, the Visual Basic Upgrade Companion's resulting source code contains clearly defined data types. For this example, var1, var2, and var3 were typed based on their usage (int and string). Also, the "ArgTypeInference" function's return value type was inferred to be int.

**C# Code Generated by the VB6 AI Migrator**

```csharp
private void typeInference()
{
    int var2 = 0;
    string var3 = "";
    string var4 = new string('\0', 50);
    var4 = StringsHelper.GetFixedLengthString(Path.GetDirectoryName(Application.ExecutablePath), 50);
    int var1 = ArgTypeInference(var2, var3, var4, Strings.Len(var4));
}

public int ArgTypeInference(int arg1, string arg2, string arg3, int arg4)
{
    MessageBox.Show(arg1.ToString(), AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
    MessageBox.Show(arg2, AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
    MessageBox.Show(arg3, AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
    MessageBox.Show(arg4.ToString(), AssemblyHelper.GetTitle(System.Reflection.Assembly.GetExecutingAssembly()));
    return 1;
}
```

### Custom Typing

We also provide a mechanism that assigns custom .NET data types; it includes variables, functions, fields, properties, among others; which implies a series of changes in the code both in the declarations and in their uses.

It can be used mainly to provide the possibility to fully qualified names of statements if deemed necessary, for example, classes with the same name but with different namespaces.

## Extensibility

### Transformations Rules

Sometimes the client needs to apply custom transformation rules to specific code patterns in order to fulfill a requirement. Here are some examples:

* Rename all properties of a class of type *string* to *str\_propertyName*.
* Make some classes implement a new interface and create a default method implementation for them.
* Transform all *foo(str1, int1, str2, int2)* method calls to *otherFoo(str1, str2, int1 + int2)*.
* Add a new function call at the start of the methods in a class, in which the code has exactly one *try-cath* block.
* Remove the *form\_load* event binding at the designer files, but keep the method handler.

  The VB6 AI Migrator team can create these custom code transformation rules to better achieve the customer-specific needs. The client only needs to define them at a macro level, by specifying the input code pattern, what conditions trigger the rule and how the output code should look like; after that, the VB6 AI Migrator team will handle the rest.

> **See also:** [Mobilize.NET Customization](/vbuc/ewis.md#mobilize-net-customization-optional)

## Windows API to Pinvoke

The Microsoft Windows application programming interface (Windows API) allows developers to call Windows OS functions directly. All programs interact with the Windows API at some point, either directly or through some other API.

Visual Basic 6 provides a mechanism to invoke methods in native code via dynamic-linked libraries (DLLs). This mechanism is possible to be used with the ***DECLARE*** statement in VB6. This statement indicates to the VB6 compiler where the procedure is located, how it is identified, its calling sequence and return type, and the string character set it uses. The Declare statement creates a reference to an external procedure and supplies this necessary information. In this way, the external procedure is called like any other method in the user code.

The following is a typical declaration and invocation of a Windows API method:

```php
Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" (
ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
Sub getUser()
  Dim buffer As String = New String(CChar(" "), 25)
  Dim retVal As Integer = getUserName(buffer, 25)
  Dim userName As String = Strings.Left(buffer, InStr(buffer, Chr(0)) - 1)
  MsgBox(userName)
End Sub
```

In this case, the *getUser* internal method displays the current user name, to do this the *GetUserNameA* external method is being exposed from *advapi32.dll* with its respective parameters and return value.

[Platform Invocation Service (PInvoke)](https://docs.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke) is a feature of Common Language Infrastructure implementations, like Microsoft Common Language Runtime, that enables managed code to call native code. This is the mechanism provided by .NET to invoke this kind of method.

This is an example of how the Beep external method is declared as PInvoke method, which could be used in anywhere of the user code:

```csharp
[DllImport("kernel32.dll")]
extern public static int Beep(int dwFreq, int dwDuration);
```

The PInvoke infrastructure supplied by .NET is a mechanism for programmers in .NET to invoke external methods in an efficient and strong way. It will provide a .NET styled syntax to expose external methods and a natural way to invoke those external methods.

In general, for every external \*.dll call, the VB6 AI Migrator generates the required interoperability data-type marshalling to allow a smooth interaction between.NET and unmanaged code. The most common changes in this feature are:

* Adds specific interoperability attributes to the signatures of upgraded API calls
* Adds error handling for the upgraded API calls.
* Generates the correct data types for pointer-type parameters
* Modifies structure generation so the marshalling of structs to Windows API calls and the copying of structures in migrated .NET applications is completely automated.

Sometimes declarations (or exposition) of an external method in .NET are easy, but invocation is sometimes complex because it has to deal with error handling, marshalling data types, and setting back values to its respective variables. This code seems to be larger and not natural, so the VB6 AI Migrator applies some refactoring to centralize all this code in methods that will contain all code related to those issues.

In this way, user code will be presented similar to the original, with no additional code to support marshalling or error handling, and this other code will be centralized in some files where the user can improve it or change it if necessary. Maintainability and removal of duplicated code are the main reasons why this approach is implemented in this way.

In addition, as stated above, a large amount of code for error handling, marshalling data types, especially if struct types are used to send or reassign return values to variables, must be generated in order to get the same behavior as VB6 had. All this code is generated by VB6 AI Migrator in those centralized files in a transparent way for all needed cases, mainly blittable types; and it will log EWIs in cases where some manual revision should be done, for non-blittable types.

### External-Marshalling Attributes for Structs

The VB6 AI Migrator is able to add marshalling information to the structures used in Windows API calls. These extra attributes allow the resulting .NET code to be coherent with most of the legacy behavior found on the unmanaged code of the Windows API DLLs.

**Original VB6 code:**

```php
Private Type ACTYLG_TYPE
    lFirstField              As Long         ' <Force proper alignment>'
    lIDN                     As Long         ' INTEGER NOT NULL'
    sCNCRCY_USER_IDN         As String * 8   ' CHAR (8) NOT NULL'
    sTABLE_ALIAS_NAME        As String * 6   ' CHAR (6) NOT NULL'
    iTABLE_UNQ_IDN_NI        As Integer      ' <Null Indicator>'
    lTABLE_UNQ_IDN           As Long         ' INTEGER'
    iTABLE_UNQ_SEQ_NUM_NI    As Integer      ' <Null Indicator>'
    iTABLE_UNQ_SEQ_NUM       As Integer      ' SMALLINT'
End Type
```

**Resulting .NET Code:**

```csharp
[Serializable][StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
private struct ACTYLG_TYPE
{
  public int lFirstField; // <Force proper alignment>
  public int lIDN; // INTEGER NOT NULL
  [Microsoft.VisualBasic.VBFixedArray(7)][System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=8)]
  public char[] _sCNCRCY_USER_IDN; // CHAR (8) NOT NULL
  [Microsoft.VisualBasic.VBFixedArray(5)][System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=6)]
  public char[] _sTABLE_ALIAS_NAME; // CHAR (6) NOT NULL
  public short iTABLE_UNQ_IDN_NI; // <Null Indicator>
  public int lTABLE_UNQ_IDN; // INTEGER
  public short iTABLE_UNQ_SEQ_NUM_NI; // <Null Indicator>
  public short iTABLE_UNQ_SEQ_NUM; // SMALLINT
  public string sCNCRCY_USER_IDN
  {
    get
    {
      return new string(_sCNCRCY_USER_IDN);
    }
    set
    {
      ArraysHelper.CopyStringToCharArray(_sCNCRCY_USER_IDN, value);
    }
  }

  public string sTABLE_ALIAS_NAME
  {
    get
    {
      return new string(_sTABLE_ALIAS_NAME);
    }
    set
    {
      ArraysHelper.CopyStringToCharArray(_sTABLE_ALIAS_NAME, value);
    }
  }

  public static ACTYLG_TYPE CreateInstance()
  {
    ACTYLG_TYPE result = new ACTYLG_TYPE();
    result._sCNCRCY_USER_IDN = new char[8];
    result._sTABLE_ALIAS_NAME = new char[6];
    return result;
  }
}
```

### Structure of generated PInvoke files

The declaration of a VB6 external method will generate two files.

The number of files will depend on the number of libraries being used in projects. It means if there are two external methods, one using a user32 library method and the other referencing a GDI library method, the VB6 AI Migrator will generate two files (user32 and GDI) in a folder inside the solution named, by default, PInvokeSafeNative. It will contain any additional code related to castings, marshalling, error handling, freeing memory, and so on, and it will have the managed code that will reference the unmanaged code.

The second two generated files (named user32 and GDItoo) will be generated in the folder named PInvokeUnsafeNative, where the PInvoke declaration code will be.

Two subfolders are created, as shown below.

```
/PInvokeSafeNative/
  Lib1
  Lib2
  ...
  LibN
/PInvokeUnsafeNative/
  Lib1
  Lib2
  ...
  LibN
```

Inside those folders, a file will be created grouping PInvoke calls per DLL. If your API calls were, for example, to user32.dll, then a file with that name will be generated and all PInvoke calls to that DLL will be arranged inside that file. The following example shows how the code is upgraded.

**Original VB6 code**

```php
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long

Private Sub Command1_Click()
  Dim titleForm1 As String
  titleForm1 = String(GetWindowTextLength(Me.hwnd) + 1, Chr$(0))
   GetWindowText Me.hwnd, titleForm1, Len(titleForm1)
End Sub
```

**.NET Code**

```csharp
//File: user32.cs (safe methods)
public static class user32
{
    public static int GetWindowText(int hwnd, ref string lpString, int cch)
    {
        return MySolutionSupport.PInvoke.UnsafeNative.user32.GetWindowText(hwnd, ref lpString, cch);
    }
    public static int GetWindowTextLength(int hwnd)
    {
        return MySolutionSupport.PInvoke.UnsafeNative.user32.GetWindowTextLength(hwnd);
    }
}

//File: user32.cs (unsafe methods)
[System.Security.SuppressUnmanagedCodeSecurity]
public static class user32
{
    [DllImport("user32.dll", EntryPoint = "GetWindowTextA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    extern public static int GetWindowText(int hwnd, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpString, int cch);

    [DllImport("user32.dll", EntryPoint = "GetWindowTextLengthA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    extern public static int GetWindowTextLength(int hwnd);
}

//File: Form1.cs
private void Command1_Click(Object eventSender, EventArgs eventArgs)
{
            string titleForm1 = new string(Strings.Chr(0), MySolutionSupport.PInvoke.SafeNative.user32.GetWindowTextLength(this.Handle.ToInt32()) + 1);
            MySolutionSupport.PInvoke.SafeNative.user32.GetWindowText(this.Handle.ToInt32(), ref titleForm1, Strings.Len(titleForm1));
}
```

### Upgrading Win API Any arguments

Any is a VB6 data type only used for external method declarations that indicates that it could receive any type.

This is a type that is not available in Visual Studio .NET, so it must be converted to a pointer (System.IntPtr) that contains the beginning of the memory address for each data type used in that argument.

The following example references an external method named LoadCursor. The second parameter is declared as Any.

```php
Declare Function LoadCursor Lib "user32" Alias "LoadCursorA" (ByVal hInstance As Long, ByVal lpCursorName As Any) As Long

Public Sub LoadSomeCursor()
  ' ...'
  Dim inst As Long, myCursorName As String
  ' ...'
  LoadCursor inst, myCursorName
End Sub
```

These are the corresponding C# and VB.NET resultant codes. You can note the declaration of the Any argument as IntPtr in C# and Integer in VB for the Unsafe methods. The Safe methods are declared depending on the uses or invocations to the respective method. Because of that, the safe method is declared as a *string* in this case and requires some castings (marshalling) to be able to send this argument as a pointer and its respective setting back.

**C#.NET**

```csharp
//[PInvokeSafeMethods]
public static int LoadCursor(int hInstance, string lpCursorName)
{
  int result = 0;
  IntPtr tmpPtr = Marshal.StringToHGlobalAnsi(lpCursorName);
  try
  {
    result = MySolutionSupport.PInvoke.UnsafeNative.user32.LoadCursor(hInstance, tmpPtr);
    lpCursorName = Marshal.PtrToStringAnsi(tmpPtr);
  }
  finally
  {
    Marshal.FreeHGlobal(tmpPtr);
  }
  return result;
}

//[PInvokeUnsafeMethods]
  [DllImport("user32.dll", EntryPoint = "LoadCursorA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
  extern public static int LoadCursor(int hInstance, System.IntPtr lpCursorName);

//…
public static void LoadSomeCursor()
{
  int inst = 0;
  string myCursorName = "";
  MySolutionSupport.PInvoke.SafeNative.user32.LoadCursor(inst, myCursorName);
}
```

**VB.NET**

```php
'[PInvokeSafeMethods]'
Public Function LoadCursor(ByVal hInstance As Integer, ByRef lpCursorName As String) As Integer
    Dim result As Integer = 0
    Dim tmpPtr As IntPtr = Marshal.StringToHGlobalAnsi(lpCursorName)
    Try
        result = MySolutionSupport.UnsafeNative.user32.LoadCursor(hInstance, tmpPtr)
        lpCursorName = Marshal.PtrToStringAnsi(tmpPtr)
    Finally 
        Marshal.FreeHGlobal(tmpPtr)
    End Try
    Return result
End Function

'[PInvokeUnsafeMethods]'
Declare Function LoadCursor Lib "user32"  Alias "LoadCursorA"(ByVal hInstance As Integer, ByVal lpCursorName As Integer) As Integer

'...'
Public Sub LoadSomeCursor()
    Dim inst As Integer
    Dim myCursorName As String = ""
    MySolutionSupport.SafeNative.user32.LoadCursor(inst, myCursorName)
End Sub
```

### Upgrading Win API String arguments

The string arguments in external methods are handled almost as a general case, but the main difference is that if the argument was declared byref or byval, it always would be converted as byref in the target code. It implies handling of byref parameters being sent to that method and the declaration of that argument as VBByRefStr (in C#).

**Original VB6 code**

```php
Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long

Public Sub GetCurUserName()
  Dim lpBuf As String * 200
  GetUserName lpBuf, 200
End Sub
```

**C# Code**

```csharp
//[PInvokeSafeMethods]
public static int GetUserName(ref string lpBuffer, ref int nSize)
{
  return MySolutionSupport.PInvoke.UnsafeNative.advapi32.GetUserName(ref lpBuffer, ref nSize);
}

//[PInvokeUnsafeMethods]
[DllImport("advapi32.dll", EntryPoint = "GetUserNameA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
extern public static int GetUserName([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpBuffer, ref int nSize);

//…
internal static void GetCurUserName()
{
  string lpBuf = new string('\0', 200);
  int tempRefParam = 200;
  MySolutionSupport.PInvoke.SafeNative.advapi32.GetUserName(ref lpBuf, ref tempRefParam);
  lpBuf = StringsHelper.GetFixedLengthString(lpBuf, 200);
}
```

**VB.NET Code**

```php
'[PInvokeSafeMethods]'
Public Function GetUserName(ByRef lpBuffer As String, ByRef nSize As Integer) As Integer
    Return MySolutionSupport.UnsafeNative.advapi32.GetUserName(lpBuffer, nSize)
End Function

'[PInvokeUnsafeMethods]'
Declare Function GetUserName Lib "advapi32"  Alias "GetUserNameA"(ByVal lpBuffer As String, ByRef nSize As Integer) As Integer

' ...'
Public Sub GetCurUserName()
    Dim lpBuf As New String(Microsoft.VisualBasic.Constants.vbNullChar, 200)
    MySolutionSupport.SafeNative.advapi32.GetUserName(lpBuf, 200)
End Sub
```

### Upgrading Win API Struct arguments

Handling and passing structures to an external method are also handled differently in the PInvoke solution. In this case, a new file is generated in the PInvokeUnsafeMethods folder, which will have the structure being passed as an argument in that external method.

It implies, additionally, that any reference to that structure has to be changed to reference this new location of the structure.

Moreover, in multiple project solutions, a merge and removal of repeated structures must be done, in order to discard many duplicated structures. Sometimes there are differences between some structures that seem very similar (same name but different fields or data type fields), in this case, a renaming is added for subsequent structures and it is possible that some manual revision must be done.

**Original VB6 Code**

```php
Type POINTAPI
  x As Long
  y As Long
End Type

Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Public Sub ObtainCursorPos()
  Dim pos As POINTAPI
  GetCursorPos pos
End Sub
```

**C# Code**

```csharp
//[PInvokeSafeMethods]
public static int GetCursorPos(ref MySolutionSupport.PInvoke.UnsafeNative.Structures.POINTAPI lpPoint)
{
    return MySolutionSupport.PInvoke.UnsafeNative.user32.GetCursorPos(ref lpPoint);
}

// [PInvokeUnsafeMethods]
[DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
extern public static int GetCursorPos(ref MySolutionSupport.PInvoke.UnsafeNative.Structures.POINTAPI lpPoint);

//[PInvokeUnsafeMethods\Structures]
public static class Structures
{
        [Serializable][StructLayout(LayoutKind.Sequential)]
        public struct POINTAPI
        {
            public int x;
            public int y;
        }
}
```

**VB.NET Code**

```python
'[PInvokeSafeMethods]'
Public Function GetCursorPos(ByRef lpPoint As MySolutionSupport.UnsafeNative.Structures.POINTAPI) As Integer
    Return MySolutionSupport.UnsafeNative.user32.GetCursorPos(lpPoint)
End Function

'[PInvokeUnsafeMethods]'
Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As MySolutionSupport.UnsafeNative.Structures.POINTAPI) As Integer

'[PInvokeUnsafeMethods\Structures]'
<System.Security.SuppressUnmanagedCodeSecurity> _
Public Module Structures
  <Serializable> _
  <StructLayout(LayoutKind.Sequential)> _
  _
  Public Structure POINTAPI
    Dim x As Integer
    Dim y As Integer
  End Structure
End Module
```

## .NET Core / .NET 5 / .NET 6 Support

VBUC offers the possibility to migrate your VB6 project to new .NET platforms like *.NET Core 3.1, .NET 5 and .NET 6*; for this, it is necessary to follow the steps to [Create a VBUC solution targeting new .NET platforms](/vbuc/get-started.md#net-core).

> See more info on [.NET Core](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-1)[ / .NET 5](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-5) [/ .NET 6](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-6)

### New project files style  (SDK style)

One of the most essential differences when choosing .NET Core and .NET 5 / .NET 6 vs .NET Framework in terms of generated code, would be the .csproj or . vbproj file since the formers use the new SDK project file style.

> See [.csproj new format](https://docs.microsoft.com/en-us/dotnet/core/tools/csproj)

**.csproj or .vbproj file in .NET Framework**

```markup
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion />
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
    ...
    <ProjectReference Include="..\UpgradeSupport\UpgradeHelpers.DB.Essentials\UpgradeHelpers.DB.Essentials.csproj">
      <Project>{B5D4A0EE-0D52-4EE8-829D-48DAF1E56B8E}</Project>
      <Name>UpgradeHelpers.DB.Essentials</Name>
    </ProjectReference>
    ...
</Project>
```

**.csproj or .vbproj file in .NET Core or .NET 5 / .NET 6**

```markup
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
  <PropertyGroup>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion />
    <TargetFrameworks>netcoreapp3.1;net5.0-windows;net6.0-windows</TargetFrameworks>
    ...
    <PackageReference Include="Mobilize.VBUC.Helpers.DB.Essentials" Version="9.0.0" />
    ...
</Project>
```

> *Notes:*
>
> * The main `<Project>` tag replaces the attributes with `Sdk`, to indicate the SDK version to use.
> * The tag `<TargetFrameworkVersion>` becomes `TargetFramework>`
>
>   &#x20;or `<TargetFrameworks>`, depending if the project is compiled into multiple platforms.&#x20;
> * In this example using .NET Core, the helpers integration  is done through NuGet; so the `<ProjectReference>` tag is changed to `<PackageReference>`, in addition to removing some unnecesary tags like `<Project>` and `<Name>`.

### Upgrade Options supported in .NET Core and .NET 5 / .NET 6

Some Upgrade Options values are not yet available for .NET Core and .NET 5 / .NET 6 migrations because of multiple reasons. In some cases, the selected feature requires a third-party library that currently does not have support for these new .NET platforms; in other cases, the third-party library might never have support. As third-party library creators update their products, we can as well enable some of these features in future releases.

The following sections provide a complete list of all Upgrade Options, grouped by category. The last column indicates the values that are enabled/disabled for .NET Core and .NET 5 / .NET 6 Migrations.

#### Data Access

| Upgrade Option | Value                                                   | .NET Core / .NET 5 / .NET 6 Support? |
| -------------- | ------------------------------------------------------- | ------------------------------------ |
| ADODB          | To ADO.NET using System.Data.Common and helpers classes | ☑                                    |
| ADODB          | To ADO.NET using SQL Client                             |                                      |
| ADODB          | To COM Interop                                          | ☑                                    |
| DAO            | To COM Interop                                          | ☑                                    |
| DAO            | To ADO.NET with helpers based on System.Data.Commons    | ☑                                    |
| OracleInProc   | To COM Interop                                          | ☑                                    |
| OracleInProc   | To System.DBConnection                                  | ☑                                    |
| RDO            | To COM Interop                                          | ☑                                    |
| RDO            | To ADO.NET using SqlClient                              | ☑                                    |
| RDO            | To ADO.NET using System.Data.Common and helpers classes | ☑                                    |
| SQLDMO         | To COM Interop                                          | ☑                                    |
| SQLDMO         | To Microsoft.SqlServer.Smo                              | ☑                                    |

#### Grids

| Upgrade Option | Value                                                 | .NET Core / .NET 5 / .NET 6 Support? |
| -------------- | ----------------------------------------------------- | ------------------------------------ |
| FPSpread       | To FarPoint Spread helper class                       |                                      |
| FPSpread       | To COM Interop                                        | ☑                                    |
| MSDataGridLib  | To COM Interop                                        | ☑                                    |
| MSDataGridLib  | To ComponentOne True DBGrid                           | ☑                                    |
| MSDataGridLib  | To System.Windows.Forms.DataGridView                  | ☑                                    |
| MSDBGridLib    | To COM Interop                                        | ☑                                    |
| MSDBGridLib    | To System.Windows.Forms.DataGridView + Helper classes | ☑                                    |
| MSFlexGrid     | To COM Interop                                        | ☑                                    |
| MSFlexGrid     | To ComponentOne FlexGrid                              | ☑                                    |
| MSFlexGrid     | To DataGridViewFlex helper class                      | ☑                                    |
| TrueDBGrid     | To COM Interop                                        | ☑                                    |
| TrueDBGrid     | To ComponentOne TrueDBGrid (.Net version)             | ☑                                    |
| TrueDBGrid     | To .NET component that extends DataGridView           | ☑                                    |
| VSFlexGrid     | To COM Interop                                        | ☑                                    |
| VSFlexGrid     | To ComponentOne FlexGrid                              |                                      |

#### Microsoft

| Upgrade Option                                     | Value                                           | .NET Core / .NET 5 / .NET 6 Support? |
| -------------------------------------------------- | ----------------------------------------------- | ------------------------------------ |
| MSACAL (Microsoft Calendar Control)                | To COM Interop                                  | ☑                                    |
| MSACAL (Microsoft Calendar Control)                | To System.Windows.Forms.MonthCalendar           | ☑                                    |
| MSComCtl2 (Microsoft Windows Common Controls-2)    | To COM Interop                                  | ☑                                    |
| MSComCtl2 (Microsoft Windows Common Controls-2)    | To native .NET Component (System.Windows.Forms) | ☑                                    |
| MSComctl (Microsoft Windows Common Controls)       | To COM Interop                                  | ☑                                    |
| MSComctl (Microsoft Windows Common Controls)       | To native .NET Component (System.Windows.Forms) | ☑                                    |
| MSComDlg (Microsoft Windows Common Dialog Control) | To COM Interop                                  | ☑                                    |
| MSComDlg (Microsoft Windows Common Dialog Control) | To native .NET Component (System.Windows.Forms) | ☑                                    |
| DataCombo                                          | To System.Windows.Forms.ComboBox                | ☑                                    |
| DataCombo                                          | To COM Interop                                  | ☑                                    |
| MSMask (Microsoft Mask Edit Control)               | To COM Interop                                  | ☑                                    |
| MSMask (Microsoft Mask Edit Control)               | To System.Windows.Forms.MaskedTextBox           | ☑                                    |
| MSWLess (Microsoft Windowless Controls)            | To COM Interop                                  | ☑                                    |
| MSWLess (Microsoft Windowless Controls)            | To System.Windows.Forms controls                | ☑                                    |
| MSXML2 (Microsoft XML)                             | To COM Interop                                  | ☑                                    |
| MSXML2 (Microsoft XML)                             | To System.Xml classes                           | ☑                                    |
| RichTextBox                                        | To COM Interop                                  | ☑                                    |
| RichTextBox                                        | To System.Windows.Forms.RichTextBox             | ☑                                    |
| SHDocVw (Microsoft Internet Controls)              | To COM Interop                                  | ☑                                    |
| SHDocVw (Microsoft Internet Controls)              | To System.Windows.Forms.WebBrowser              | ☑                                    |

#### Others

| Upgrade Option          | Value                                              | .NET Core / .NET 5 / .NET 6 Support? |
| ----------------------- | -------------------------------------------------- | ------------------------------------ |
| Accusoft                | To COM Interop                                     | ☑                                    |
| Accusoft                | To Accusoft.NET Version                            | ☑                                    |
| ActiveBarLibrary        | To COM Interop                                     | ☑                                    |
| ActiveBarLibrary        | To DevExpress.XtraBars                             |                                      |
| C1Elastic               | To COM Interop                                     | ☑                                    |
| C1Elastic               | To ComponentOne controls                           | ☑                                    |
| C1Elastic               | To System.Windows.Forms.Panel                      | ☑                                    |
| C1Tab                   | To COM Interop                                     | ☑                                    |
| C1Tab                   | To System.Windows.Forms.TabControl                 | ☑                                    |
| COMSVCSLib              | To COM Interop                                     | ☑                                    |
| COMSVCSLib              | To System.EnterpriseServices                       |                                      |
| CRAXDRT\_CRVIEWERLibCtl | To COM Interop                                     | ☑                                    |
| CRAXDRT\_CRVIEWERLibCtl | To CrystalReports                                  | ☑                                    |
| CrystalReport           | To COM Interop                                     | ☑                                    |
| CrystalReport           | To CrystalReport.NET                               |                                      |
| CSTextLib               | To COM Interop                                     | ☑                                    |
| CSTextLib               | To ComponentOne C1Input controls                   | ☑                                    |
| CSTextLib               | To System.Windows.Forms controls                   | ☑                                    |
| CTTips                  | To COM Interop                                     | ☑                                    |
| CTTips                  | To System.Windows.Forms.ToolTip                    | ☑                                    |
| CWUIControlsLib         | To COM Interop                                     | ☑                                    |
| CWUIControlsLib         | To NationalInstruments Library                     |                                      |
| fpBtnAtlLibCtl          | To COM Interop                                     | ☑                                    |
| fpBtnAtlLibCtl          | To System.Windows.Forms.Button                     | ☑                                    |
| ListPro                 | To COM Interop                                     | ☑                                    |
| ListPro                 | To System.Windows.FOrms.ComboBox helper class      | ☑                                    |
| MemoLibfpMemo           | To COM Interop                                     | ☑                                    |
| MemoLibfpMemo           | To System.Windows.Forms.TextBox                    | ☑                                    |
| MSAccessToNet           | To COM Interop                                     | ☑                                    |
| MSAccessToNet           | MSAcessToNET To DotNet Version                     |                                      |
| PictureBox              | To System.Windows.Forms.PictureBox                 | ☑                                    |
| PictureBox              | To System.Windows.Forms.PictureBox helper class    | ☑                                    |
| Printer                 | To .NET Printer helper class                       | ☑                                    |
| Printer                 | To PowerPacks helper class                         |                                      |
| Scripting               | To COM Interop                                     | ☑                                    |
| Scripting               | To .NET classes                                    | ☑                                    |
| TDBDate6                | To COM Interop                                     | ☑                                    |
| TDBDate6                | To System.Windows.Forms.DateTimePicker             | ☑                                    |
| TDBTime6                | To COM Interop                                     | ☑                                    |
| TDBTime6                | To System.Windows.Forms.DateTimePicker             | ☑                                    |
| TeeChart                | To COM Interop                                     | ☑                                    |
| TeeChart                | To Steema TeeChart for .NET v4                     | ☑                                    |
| VsPrinter               | To COM Interop                                     | ☑                                    |
| VsPrinter               | To ComponentOne C1PrintPreviewControl helper class |                                      |
| WshRuntimeLib           | To COM Interop                                     | ☑                                    |
| WshRuntimeLib           | To Microsoft.Win32.RegistryKey helper class        | ☑                                    |
| XArray                  | To COM Interop                                     | ☑                                    |
| XArray                  | To System.Array                                    | ☑                                    |
| XArrayDB                | To COM Interop                                     | ☑                                    |
| XArrayDB                | To System.Data.DataTable helper class              | ☑                                    |

#### Code Conversion

| Upgrade Option                             | Value                                                                         | .NET Core / .NET 5 / .NET 6 Support? |
| ------------------------------------------ | ----------------------------------------------------------------------------- | ------------------------------------ |
| Shell32                                    | To System.Diagnostics Methods                                                 | ☑                                    |
| Shell32                                    | To PInvoke                                                                    | ☑                                    |
| GoSub Conversion (C#)                      | Do not convert GoSub statements                                               | ☑                                    |
| GoSub Conversion (C#)                      | Convert GoSub statements to C# local function                                 | ☑                                    |
| ActiveX                                    | .NET Assemblies with COM Visible                                              |                                      |
| ActiveX                                    | Out process and Application Domains using Helper classes                      |                                      |
| ActiveX                                    | Standard .NET Assemblies                                                      | ☑                                    |
| Generate Auto-Implemented Properties (C#)  | On                                                                            | ☑                                    |
| Generate Auto-Implemented Properties (C#)  | Off                                                                           | ☑                                    |
| Comment Out Dead Code                      | On                                                                            | ☑                                    |
| Comment Out Dead Code                      | Off                                                                           | ☑                                    |
| Convert HelpFile and HelpContextID Feature | Do not Convert HelpFile and HelpContextID Feature                             | ☑                                    |
| Convert HelpFile and HelpContextID Feature | Convert HelpFile and HelpContextID Feature using support class                | ☑                                    |
| Default Property Resolution                | Static code analysis and helper classes                                       | ☑                                    |
| Default Property Resolution                | Static code analysis only                                                     | ☑                                    |
| Error Handling                             | Leave On Error Statements (VB.NET Only)                                       | ☑                                    |
| Error Handling                             | Convert to Try-Catch                                                          | ☑                                    |
| Error Handling                             | To Try-Catch With Lambdas(C# only)                                            | ☑                                    |
| Form Load                                  | FormLoad mechanism upgraded using a helper                                    | ☑                                    |
| Form Load                                  | FormLoad event upgraded as a method invoked from form constructor             | ☑                                    |
| Form Load                                  | FormLoad event upgraded to .NET native event                                  | ☑                                    |
| Free COM bjects                            | Free COM Objects memory using helper                                          |                                      |
| Free COM bjects                            | Free COM Objects memory manually                                              | ☑                                    |
| Late Binding Resolution                    | Static code analysis + helper classes                                         | ☑                                    |
| Late Binding Resolution                    | Static code analysis only                                                     | ☑                                    |
| Late Binding Resolution                    | Static code analysis + dynamic variables                                      | ☑                                    |
| Line And Shape                             | Helper class                                                                  | ☑                                    |
| Line And Shape                             | PowerPack and Helper class                                                    | ☑                                    |
| Mid/Left/Right Strings Functions           | Helper class functions                                                        | ☑                                    |
| Mid/Left/Right Strings Functions           | Native .NET System.String class functions                                     | ☑                                    |
| Mid/Left/Right Strings Functions           | Support function in Microsoft.VisualBasic.Compatibility.VB6.Support namespace |                                      |
| Generate Skeletons                         | On                                                                            | ☑                                    |
| Generate Skeletons                         | Off                                                                           | ☑                                    |
| Stubs Generation                           | Upgrade Stubs generation for non upgraded element                             | ☑                                    |
| Stubs Generation                           | Upgrade Note indicating not updated elements during upgrade process           | ☑                                    |
| Remove Unused Local Variables              | On                                                                            | ☑                                    |
| Remove Unused Local Variables              | Off                                                                           | ☑                                    |
| VBA.Collection Conversion                  | To System.Collections native .NET classes                                     | ☑                                    |
| VBA.Collection Conversion                  | To System.Collections.Specialized.OrderedDictionary native .NET class         | ☑                                    |

#### Sheridan

| Upgrade Option                   | Value                                     | .NET Core / .NET 5 / .NET 6 Support? |
| -------------------------------- | ----------------------------------------- | ------------------------------------ |
| SSActiveTabPanel                 | To COM Interop                            | ☑                                    |
| SSActiveTabPanel                 | To System.Windows.Forms.TabControl        | ☑                                    |
| SSActiveToolBars                 | To COM Interop                            | ☑                                    |
| SSActiveToolBars                 | To System.WIndows.Forms.ToolStrip         | ☑                                    |
| SSActiveTreeView                 | To COM Interop                            | ☑                                    |
| SSActiveTreeView                 | To System.Windows.Forms.TreeView          | ☑                                    |
| SSCalendarWidgets                | To COM Interop                            | ☑                                    |
| SSCalendarWidgets                | To System.Windows.Forms Controls          | ☑                                    |
| SSDataWidgets\_B                 | To COM Interop                            | ☑                                    |
| SSDataWidgets\_B                 | To Infragistics UltraSuite(.NET Version)  | ☑                                    |
| SSDataWidgets\_B                 | To ComponentOne (.NET Version)            | ☑                                    |
| SSDesignerWidgetsTabs            | To COM Interop                            | ☑                                    |
| SSDesignerWidgetsTabs            | To System.Windows.Forms.TabControl        | ☑                                    |
| SSListBar                        | To COM Interop                            | ☑                                    |
| SSListBar                        | To Infragistics UltraWinListBar.NET Suite |                                      |
| Convert Empty SSPanels To Labels | On                                        | ☑                                    |
| Convert Empty SSPanels To Labels | Off                                       | ☑                                    |
| SSSplitter                       | To COM Interop                            | ☑                                    |
| SSSplitter                       | To System.Windows.Forms.SplitContainer    | ☑                                    |
| Threed                           | To COM Interop                            | ☑                                    |
| Threed                           | To System.Windows.Forms Controls          | ☑                                    |


---

# 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/features.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.
