If you read virtually all books and articles related to VB6 migration, you'll learn that VB.NET doesn't support the Gosub keyword, therefore you had to manually refactor your VB6 apps and turn those Gosubs into calls to separate method.

All these articles and books were clearly written before VB Migration Partner made its debut, because we have demonstrated that the inability to convert Gosub keywords to VB.NET was only a limitation of the conversion engine used by the Upgrade Wizard that comes with Visual Studion .NET.

In fact, since its early beta versions VB Migration Partner has always been able to handle Gosub keywords and its On...Gosub variant. Translating a Gosub keyword isn't at all difficult if you think that a Gosub/Return pair can be simulated by a Goto plus another Goto that brings execution back to the statement following the Gosub. It's a simple technique and I show how to implement it during my Tips, Tracks, and Techniques in Migrating VB6 Applications to .NET 75-minute speech. (BTW, if you are attending VSLive! in Las Vegas, don't miss this session... it's tomorrow at 11 am.) Actually, it's such a simple technique that I always wondered why Upgrade Wizard didn't implement it.

Rendering Gosub/Return by means of Goto pairs ensures full functional equivalence between the original VB6 code and the generated VB.NET code, but has one defect: it makes your code less readable than it should. For these reason, a few users asked for a better way of dealing with this VB6 syntax.

The obvious solution was to extract the code portion pointed to by the Gosub keyword into a separate method and replace the Gosub with a call to that external method. The code in the external method must be able to access some (or all) variables in the original code, therefore it is necessary to pass these variables as ByRef parameters to the external method. Finally, if the original method included an On Error Resume Next statement, this statement has to be present in the external method as well.

Implmenting all these features wasn't a breeze, but we managed to do it and we are very proud of the result. As far as we know, VB Migration Partner is the first and only VB conversion tool that has this feature

Enabling Gosub refactoring is as easy as adding a ConvertGosubs pragma. Like most pragmas, it can have project-, file-, and method-level scope, therefore you can decide where exactly it has to be applied. In most cases, the best approach is adding it to the master VBMigrationPartner.pragmas file, so that all your migration projects will use it. 

    '## project:ConvertGosubs True

(You can disable this feature inside a specific file or method by simply inserting another pragma with narrower scope and False in its argument.) Consider the following VB6 code:

Function GetValue(x As Integer, id As String) As Integer
    '## ConvertGosubs True
    On Error Resume Next
   
    Dim s As String, name As String
    s = "ABC"
   name = "Code Architects"
    GoSub BuildResult
    Exit Function

BuildResult:
    GetValue = x + Len(s) + Len(name)
    Return
End Function

VB Migration Partner detects that the code that begins at the BuildResult label (a.k.a. the target label) can be safely refactored to a separate method that receives four arguments. The result of the conversion is therefore:

    Public Function GetValue(ByRef x As Short, ByRef id As String) As Short
        Dim s As String
        Dim name As String
        On Error Resume Next

        s = "ABC"
        name = "Code Architects"
        Gosub_GetValue_BuildResult(x, GetValue, s, name)
        Exit Function
    End Function

    Private Sub Gosub_GetValue_BuildResult( _
            ByRef x As Short, ByRef GetValue As Short, _
            ByRef s As String, ByRef name As String)
        On Error Resume Next
        GetValue = x + Len6(s) + Len6(name)
    End Sub

Notice that the external method contains an On Error Resume Next statement, because the original GetValue method also contains this statement. Also notice that the ID parameter isn't passed as an argument to the external method because it isn't referenced by the code inside it.

All arguments to the new Gosub_GetValue_BuildResult method are passed by reference, so that the caller can receive any value that has been modified inside the method (as is the case with the GetValue parameter in previous example.) You can have VB Migration Partner optimize this passing mechanism and use ByVal if possible by passing True as the second argument to the ConvertGosubs pragma:

    '## ConvertGosubs True, True

If this optimization is used in the above code, the separate method is rendered as follows:

    Private Sub Gosub_GetValue_BuildResult( _
           ByVal x As Short, ByRef GetValue As Short, _
           ByVal s As String, ByVal name As String)
        On Error Resume Next
        GetValue = x + Len6(s) + Len6(name)
    End Sub

If you don’t like the name that VB Migration Partner assigns to the automatically-generated method, you can easily change it by means of a PostProcess pragma:

    '## PostProcess "Gosub_GetValue_BuildResult", "AssignValueResult"

It is important to keep in mind that the conversion of a Gosub block of code into a separate method isn’t always possible. More precisely, VB Migration Partner can perform this conversions only if all the following conditions are met:

a) The method doesn't contain any Resume statement. (On Error Resume Next is OK, though).
b) The target label isn't located inside a If, Select, For, Do, or Loop block.
c) The target label isn't referenced by a Goto, On Goto/Gosub, or On Error statement.
d) The target label must be preceded by a Goto, Return, End, Or Exit Sub/Function/Property statement.
e) The code block must terminate with an unconditional Return, or an End Sub/Function/Property statement.  (Blocks that terminate with Exit Sub/Function/Property statements aren't converted.)
f) The block of code between the target label and the closing Return/End statement doesn't contain another label.

If the conversion of a specific Gosub isn't possible, VB Migration Partner reverts to the default way of converting Gosub/Return (i.e. using Goto pairs).