Starting with version 1.10, VB Migration Partner can replace old-styled On Error Goto statements into structured exception handling (SEH) based on the Try-Catch block. You can activate this feature by means of the UseTryCatch pragma, which can have project-, file-, and method-level scope. For example, the following VB6 code:

    '## UseTryCatch

    Sub Test()
        On Error Goto ErrorHandler
        ' method body
    ErrorHandler:
        ' error handler
    End Sub

is translated to the following VB.NET code:

    Sub Test()
        Try
            ' IGNORED: On Error Goto ErrorHandler
           ' method body

        Catch _ex As Exception
            ' IGNORED: ErrorHandler:
            ' error handler

        End Try
    End Sub

In case you are wondering why you need a pragma to tell VB Migration Partner to perform this transformation, please consider that this refactoring feature can't be performed in a number of occasions. More precisely, VB Migration Partner can insert a Try-Catch block only if ALL the following conditions are met:

 

  1. The method contains only a single On Error GoTo <label> method.
  2. The On Error GoTo <label> statement doesn’t appear inside a conditional block such as If, For, Select Case, and isn’t preceded by a GoTo statement.
  3. The method doesn’t contain GoSub, Resume, or Resume Next statements. (Resume <label> statements are acceptable, though)
  4. There is no Goto statement in the method body that points to a label that is defined in the error handler. (Notice that it is ok if a GoTo in the error handler points to a label defined in the method body.)
  5. If the method contains one or more On Error Goto 0 statements, such statements must immediately precede a statement that causes exiting from the current method, e.g. Exit Sub or End Function.
  6. If the current method is a Property Let procedure, there must not be a Property Set procedure for the same property. Likewise, If the current method is a Property Set procedure, there must not be a Property Let procedure for the same property.

For example, the following VB6 code:

    '## UseTryCatch
    Sub Test()
        On Error Goto ErrorHandler
        ' method body
        If x > 0 Then GoTo ErrorHandler2

    ErrorHandler:
        ' error handler
    ErrorHandler2:
        ' do something here
    End Sub

can't be converted to VB.NET using a Try-Catch block because a GoTo statement in the method body points to a label that is defined in the error handler.

By default, VB Migration Partner inserts a Try-Catch also if the method contains the On Error Resume Next statement plus another executable statement. For example, the following VB6 code:

    Function Reciprocal(ByVal x As Double) As Double
        '## UseTryCatch True
        On Error Resume Next
        Reciprocal = 1 / x
        ' returns zero if an error occurs (e.g. X is zero)
    End Function


contains only two executable statements (including On Error Resume Next) and is converted to:

    Function Reciprocal(ByVal x As Double) As Double
        Try
            Return 1 / x
            ' returns zero if an error occurs (e.g. X is zero)
        Catch
            ' Do nothing if an error occurs
        End Try
    End Function


Methods with three or more executable statements can be converted using Try Catch if you specify a value higher than 2 in the second argument for the UseTryCatch pragma. For example, all methods with up to 5 executable statements under the scope of the following pragma:
        '## UseTryCatch True, 5
are converted using a Try-Catch block.

Notice that the UseTryCatch pragma can be used together with the AutoDispose Force pragma, in which case VB Migration Partner generates a complete Try-Catch-Finally block. Combining the AutoDispose and UseTryCatch pragma can lead to complex Try-Catch-Finally blocks that can handle your errors and correctly dispose of your variables at the same time. For example, consider this VB6 method:

'## AutoDispose Yes
'## UseTryCatch

Sub Test()
     On Error Goto ErrHandler
     Dim cn As New ADODB.Connection
     Dim rs As New ADODB.Recordset
     '  opens the connection and the recordset
     cn.Open MyConnString
     rs.Open "SELECT * FROM Employees", cn
     ' …
     Exit Sub
ErrHandler:
     MsgBox "An error has occurred"
End Sub

This is how VB Migration Partner converts this code to VB.NET:

    Public Sub Test()
        Dim cn As New ADODB.Connection
        Dim rs As New ADODB.Recordset
        Try
            ' IGNORED: On Error GoTo ErrHandler
           '  opens the connection and the recordset
           cn.Open(myconnstring)
           rs.Open("SELECT * FROM Employees", cn)
           ' …
           Exit Sub
        
        Catch _ex As Exception
           ' IGNORED: ErrHandler:
           MsgBox6("An error has occurred")
        Finally
           ' Clean up all disposable variables
           SetNothing6(cn)
           SetNothing6(rs)
        End Try
    End Sub

The SetNothing6 method is defined in VB Migration Partner support library. In addition to setting the variable to Nothing, this helper method invokes its Dispose method and - just as important - if the variable points to a COM object (as in this case), it removes the object from memory. (Many developers believe that you just need a call to Marshal.ReleaseComObject method to release a COM object, but it isn't always true because of a little-known bug: the SetNothing6 method takes all the necessary steps to ensure that the COM object is actually released).

Interestingly, VB Migration Partner has automatically recognized that the Recordset and Connection objects are disposable objects and require a call to SetNothing6.

In case you aren't familiar with .NET and the so-called undeterministic finalization issue, here is the short story: if you instantiate a disposable object - that is, an object that takes system resources such as a file, a database connection, a Windows API handle, etc - you MUST invoke its Dispose method before setting it to Nothing. If you fail to do so, you might introduce a noticeable overhead in your application (in the best case) or even a resource leakage that might crash your code in the long run (in the worst case).

As far as we know, VB Migration Partner is the only VB6 conversion tool that can automatically handle disposable objects in such a safe way.