Upgrading VB6 Projects to VB.NET

This article describes some of the many differences between VB6 and VB.NET. Much of the current VB6 code base will not run under VB.NET due to changes in VB.NET's syntax and language, its use of the new common runtime, and its switch to WinForms from the VB6 form model.

Visual Basic.NET includes an upgrade tool to assist in converting VB6 projects to .NET. The tool adds an upgrade report to your project listing any problems and inserts comments into your code and To Do items into the new Task List indicating where additional changes need to be made.

However, understanding the following changes can help simplify migrating your existing VB6 code. For further information on this topic, visit Microsoft's web site.

Beside the changes discussed here there are many new and fundamentally different language features and programming concepts incorporated into the VB.NET platform. The big ones include: Polymorphism, Inheritance and Encapsulation (PIE), operation overloading, parameterized constructors, class-level attributes and operations.

To understand VB.Net you really need to learn more about these features. For example, the Form Load and Class Initialize events are replaced by the Sub New procedure which is a constructor.

A good place to learn about these changes is my Object Oriented Programming (OOP) article.

ADO | APIs | Arrays | Boolean Operations | Controls | Constants | Data Types | Default Properties

Early Binding | Free Threading | IDE | Let/Get | Old Commands | New Commands | Parameter Passing

Resize Code | Variable Declaration | WinForms


Passing Parameters
Parameters can be passed to a procedure in one of two ways. Either by reference (ByRef) or by value (ByVal). When you use the by reference method, changes made to parameters' values in a sub procedure are known when control returns back to the calling procedure.

ByRef is the default method of parameter passing in VB6 and prior versions when the parameter's data type is an intrinsic one such as Integer, Long, Boolean, String, etc.

Then second method is pass by value (ByVal). This is the default for all non-intrinsic data types. When passed by value, the calling procedure knows nothing about changes made to the parameter's value in a sub procedure.

VB.NET passes all parameters ByVal. Thus, don't rely on the default behavior and always explicitly specify ByVal or ByRef in your parameter lists.

Optional Parameters
VB allows you to define variant parameters to a procedure as being optional and not required. The code within a VB6 procedure then checks to see if the parameter contains a value using the IsMissing keyword. For example:

   Function fDouble (Optional A)
      If IsMissing(A) Then
         fDouble = Null
         fDouble = A * 2
   End If

Since VB.NET does not support the IsMissing keyword, you should always use a default value on your optional parameters:

   Function fDouble (Optional A = 0)

Variable Declaration

Always declare variables on separate lines. I always thought this to be good practice anyway.

   Dim lngOne As Long
   Dim lngTwo As Long

The above statement declares both variables as Long.

   Dim lngOne, lngTwo As Long 

This statement, however, declares lngOne as a Variant (which is not supported in .NET) and lngTwo as a Long.

Data Types

Since VB.NET uses a common runtime among Visual Studio languages, data types in VB needed to be brought into line with those of other languages. Here are some of the data type changes.






16 bits



32 bits



64 bits



Use the new 'Object' data type



Use Decimal in VB6 or Decimal or Long in VB.NET



Available* in VB6. Native in VB.NET



VB.NET doesn't support fixed length strings

VB.NET no longer supports the Variant and Currency data types. VB documentation has always warned to minimize your use of variants. In .Net they are not supported. Use the object data type instead.

The currency data type stores values as 64-bit integers, scaled by 10,000 to give a fixed-point number with 15 digits to the left of the decimal point and 4 digits to the right. In VB.NET you can replace currency variables with the new 64-bit Long variable or the 64-bit decimal data type.

In VB6, you can also use the decimal data type. Although you cannot declare a variable as decimal, you can declare it as variant then use the cDec function to make its subtype decimal.


Most APIs that take numeric arguments expect 32-bit values. In VB6 that's a Long data type. In VB.NET a long is 64-bits and will not work with 32-bit API calls. Your .NET API parameters will have to be changed or cast to the Integer data type prior to invoking the API.

Many APIs will no longer be callable from VB and others will have replacements. Some that pass strings will need tweaking to pass the correct string or Null value. Check the VB.NET Help for more information.

APIs will need to be handled on a case by case basis. Your best bet is to isolate all your API calls so changes only need to be made in a single location in your code. The upgrade tool will attempt to convert API calls by creating wrappers for them. However, manual intervention will be required.

Deprecated Commands

VB.NET no longer supports the VarPtr, ObjPtr and StrPtr functions which retrieved the underlying memory address of variables. It also no longer supports the LSet command which was used to convert one user defined type to another.

Some defunct keywords are: GoSub, Let, Is Missing, DefBool, DefByte, DefLng, DefCur, DefSng, DefDbl, DefDec, DefDate, DefStr, DefObj and DefVar as well as On x Goto.

Here are more affected commands:


VB.NET Namespace


































GetType (returns an object of class Type, which has properties to get information.

The Set command is no longer supported. That means

   Set objObject = objAnotherObject


   objObject = objAnotherObject

The Debug command changes from.




New Commands and Keywords

VB.NET introduces many new keywords with no counterpart in VB6. Many of these are a result of the added object oriented features.





Points to a base class to use for inheritance

Inherits System.Winforms.Form


Refernces the base calss for use in the subclass' code

StringProperty = MyBase.StringProperty


All instances of a class should share a variable in a class

Public Shared Baselocation As String


New error handling. "Try" starts the code with error handling enabled. "Catch" indicates the code to use to process an error. "Finally" indicates the code to run regardless. "Throw" is used to raise an error.

End Try


Used in a property that contains only a "Get"

Public ReadOnly Property StrProperty() As String


Used in a property that contains only a "Set"

Public WriteOnly Property StrProperty() As String


New character datatype

Dim chrInitial As Char


Makes an object hierarchy (namespace) available in a module

Imports System.WinForms


Specifies a namespace for a module

NameSpace MyAppName


Tags a method as part of a publically available Web Service

Public Function <Webmethod()>
 MyMethod(sIn As String) As String


Indicates there's more than one version of a function and the compiler can distinguish among them by the input parameters

'Both of these in same module:
Overloads Sub Print(s As String)
Overloads Sub Print(l As long)


Indicates a member overrides the identically named member in the base class

Inherits MyBaseClass
Overrides Function X() As String


A member is allowed to be overridden in any class derived from the base class

Overridable Function X() As String


Indicates that any class that derives from this class must supply an override for this member.

MustOverride Function X() As String


This member is only available to classes derived from this class

Protected Sub Clear()


In VB6 declaring an array

   Dim Items(5) As String

gives you 6 items from index 0 to index 5. In VB.NET, this same declaration will yield 5 elements from index 0 through index 4. Be on the look out for "out of bounds" type errors. Also, all arrays in .NET must now be zero-based.

Default Properties

VB6 allows you to reference the default property of a control or object without specifying the name of the property. VB.NET disallows this.

   txtMyText = "Hello"
   rst!("name") = "Dave"
   rst!name = "Dave"

The above statements must be replaced with:

   txtMyText.text = "Hello"
   rst!("name").value = "Dave"
   rst!name.value = "Dave"

References to Form Controls

Controls on a form are no longer public in VB.NET. Thus, form2 cannot reference form1.text1.text. What you now need to do is add public Let and Get property procedures to the form for each control property you want to reference from another form. By the way, Let is no longer supported, read on for more info.

You can also declare the control you want to reference as Public Shared but that is not the recommended approach.

Form Resize Code

VB.NET has added new features such as Control Anchoring which lets a form automatically resize controls as a user resizes the form. Also, Control Docking lets controls be docked to any side of a form.

As a result of these changes much of your form's resize code may not be needed.

VB Integrated Development Environment

The VB Integrated Development Environment (IDE) is now fully integrated with the Visual Studio.NET IDE. Thus VB.NET has a new language-neutral extensibility model. VB.NET add-ins are now VS.NET add-ins. While this lets you create a VB.NET add-in that changes a Visual C# form, your existing add-ins need to change to reflect the new extensibility model.

Data Access Methods

VB.NET is geared towards ADO. All bound controls will work only with ADO. Although DAO and RDO will still work, with some minor changes, you cannot bind DAO or RDO recordsets to controls.

Let and Get Property Procedures

The syntax for Let and Get user defined property procedures has changed. Instead of being two separate property procedures, the logic for both Let and Get are combined into a single procedure. For example:

   Property Get MyProperty() As Integer
      m_MyProperty = MyProperty
   End Property

   Property Let MyProperty(NewValue As Integer)
      m_MyProperty = NewValue
   End Property


   Property MyProperty() As Short
         m_MyProperty = MyProperty
      End Get
         m_MyProperty = Value
      End Set
   End Property

Windows Forms (WinForms)

Windows Forms (WinForms) replace the VB6 forms. Winforms have many new and improved features such as in place menu editing and better Graphical Display Interface (GDI+) support resulting in better graphics handling.

You can now use transparency, layering, alpha blending, gradient effects, etc. for fancier looking forms (see my Irregular Form samples for explanations of these terms).

However, along with this comes a similar but different form object model. Here are some differences from VB6 forms:

  • Winforms do not support the OLE Container, shape or line controls.
  • Winforms use new Circle, CLS, PSet, Line and Point graphic commands.
  • Winforms do not support Dynamic Data Exchange (DDE) or the form.PrintForm method.
  • Winforms and controls do not expose a .Name property at runtime. You cannot enumerate the controls collection looking for a control with a given name.
  • Winforms use a different menu system, drag and drop and clipboard object model.
  • Setting a timer control's interval to 0 does not disable the timer.

Visual Inheritance
Means an organization can define a standard base form containing items such as a corporate logo and a common toolbar. This form can be used by developers through inheritance and extended to meet the requirements of specific applications while promoting a common user interface across the organization. The creator of the base form can specify which elements can be extended and which must be used as is, ensuring that the form is reused appropriately.

Early Binding

When upgrading a VB6 project to VB.NET the upgrade tool attempts to convert references to old, obsolete or missing object properties and methods to the new ones. For example,

   Dim o As Object
   Set o = Me.Label1
   o.Label1 = "Name:"
   o.Label1.Caption = "Name:"

Both statements set Label1's caption to "Name:" in VB6. In VB.NET the .caption property is now the .text property. Since the object was declared using late binding the upgrade tool doesn't know what type of object "o" refers and cannot update the code.

If early binding was used as show below, the tool would successfully convert your code to use the new .text property.

   Dim o As Label
   Set o = Me.Label1
   o.Label1.Caption = "Name:"

Boolean and Logical Operations

Logical versus BitWise Operations
The Not, And and Or operators work differently in VB.NET. In VB6 and earlier, these functions performed either logical or Bitwise operations depending on the context they were used in. If all their operands were of type boolean they performed logical operations. Otherwise they performed bitwise operations.

Now they will only perform logical operations. VB.NET introduces the BitAnd, BitOr, BitNot and BitXor keywords to perform bitwise operations.

If your existing VB6 code uses the logical operators on non-boolean values either you will get incorrect results or your code will convert to use the slower VB6.And, VB6.Or and VB6.Not compatibility functions.

Short Circuit Logic
New to VB.NET is short circuit logic. Short circuit logic only evaluates multiple conditions in a logical statement if necessary. Consider:

   Dim b As Boolean
   b = Function1() And Function2()

Under VB6 both functions are evaluated. Under VB.NET if function1 is false, function2 is not evaluated since "b" cannot be True. While this is more efficient it can cause problems. If a side effect of evaluating function2 is the setting of a global variable, that variable will no longer get set. This will produce the desired effect:

   Dim b As Boolean
   Dim c As Boolean
   Dim d As Boolean
   c = Function1()
   d = Function2()
   b = c AndAlso d

Use Constants Instead of Underlying Values

You are safer using named constants in your code rather than the underlying value. VB6 constants will convert to the correct value when upgraded to VB.NET. But if you use the actual value, you may end up with an incorrect value hard coded in your program.

The best example is that of the constant True which has a value of -1 in VB6. VB.NET, however, uses a value of 1 to mean True.

Free Threading

Code written is VB6 is synchronous. Each line of code must be executed before the next one is processed. With .NET you can spawn a thread to perform a long-running task, execute a complex query, or run a multipart calculation while the rest of the application continues, providing asynchronous processing.

   Sub CreateThread(
      Dim b As BackGroundTask
      Dim t As Thread
      Set b = New BackGroundTask()
      Set t = New Thread(New ThreadStart(AddressOf bTask))
   End Sub

   Class BackGroundTask
      Sub Task
         . . .
      End Sub
   End Class

About TheScarms
About TheScarms

Sample code
version info

If you use this code, please mention "www.TheScarms.com"

Email this page

© Copyright 2024 TheScarms
Goto top of page