vb6-legacy

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

VB6 Legacy and COM Interop

VB6遗留系统与COM互操作

Patterns for maintaining VB6 code and strategies for migrating to VB.NET with COM interop.
本文介绍维护VB6代码的模式,以及借助COM互操作迁移至VB.NET的策略。

VB6 to VB.NET Migration

VB6 迁移至 VB.NET

Key Differences

核心差异

vb
' VB6 - Variant types
Dim data As Variant
data = 123
data = "Hello"

' VB.NET - Strong typing with Option Strict On
Option Strict On
Dim data As Object  ' Still avoid when possible
Dim number As Integer = 123
Dim text As String = "Hello"

' VB6 - Default properties
Text1.Text = "Hello"
Text1 = "Hello"  ' Uses default Text property

' VB.NET - Explicit properties required
TextBox1.Text = "Hello"  ' Must be explicit

' VB6 - ByRef default
Sub ProcessData(data As String)  ' ByRef by default

' VB.NET - ByVal default
Sub ProcessData(data As String)  ' ByVal by default
Sub ProcessData(ByRef data As String)  ' Explicit ByRef

' VB6 - On Error
On Error Resume Next
On Error GoTo ErrorHandler

' VB.NET - Try-Catch
Try
    ' Code
Catch ex As Exception
    ' Handle error
End Try
vb
' VB6 - Variant types
Dim data As Variant
data = 123
data = "Hello"

' VB.NET - Strong typing with Option Strict On
Option Strict On
Dim data As Object  ' Still avoid when possible
Dim number As Integer = 123
Dim text As String = "Hello"

' VB6 - Default properties
Text1.Text = "Hello"
Text1 = "Hello"  ' Uses default Text property

' VB.NET - Explicit properties required
TextBox1.Text = "Hello"  ' Must be explicit

' VB6 - ByRef default
Sub ProcessData(data As String)  ' ByRef by default

' VB.NET - ByVal default
Sub ProcessData(data As String)  ' ByVal by default
Sub ProcessData(ByRef data As String)  ' Explicit ByRef

' VB6 - On Error
On Error Resume Next
On Error GoTo ErrorHandler

' VB.NET - Try-Catch
Try
    ' Code
Catch ex As Exception
    ' Handle error
End Try

Common Migration Issues

常见迁移问题

vb
' VB6 - Fixed-length strings
Dim name As String * 50

' VB.NET - Use regular string and PadRight
Dim name As String = "John".PadRight(50)

' VB6 - Currency type
Dim amount As Currency

' VB.NET - Use Decimal
Dim amount As Decimal

' VB6 - Control arrays
Dim TextBox(5) As TextBox

' VB.NET - Use collection
Dim textBoxes As New List(Of TextBox)()

' VB6 - Let/Set keywords
Let x = 5
Set obj = New MyClass

' VB.NET - Assignment without keywords
Dim x As Integer = 5
Dim obj As New MyClass()
vb
' VB6 - Fixed-length strings
Dim name As String * 50

' VB.NET - Use regular string and PadRight
Dim name As String = "John".PadRight(50)

' VB6 - Currency type
Dim amount As Currency

' VB.NET - Use Decimal
Dim amount As Decimal

' VB6 - Control arrays
Dim TextBox(5) As TextBox

' VB.NET - Use collection
Dim textBoxes As New List(Of TextBox)()

' VB6 - Let/Set keywords
Let x = 5
Set obj = New MyClass

' VB.NET - Assignment without keywords
Dim x As Integer = 5
Dim obj As New MyClass()

COM Interop from VB.NET

从VB.NET进行COM互操作

Early Binding (Type Library Reference)

早期绑定(类型库引用)

vb
' Add COM reference in project
' Tools -> Add Reference -> COM -> Excel Object Library

Imports Excel = Microsoft.Office.Interop.Excel

Public Sub ExportToExcel(data As DataTable)
    Dim excelApp As Excel.Application = Nothing
    Dim workbook As Excel.Workbook = Nothing
    Dim worksheet As Excel.Worksheet = Nothing

    Try
        excelApp = New Excel.Application()
        workbook = excelApp.Workbooks.Add()
        worksheet = CType(workbook.Worksheets(1), Excel.Worksheet)

        ' Write headers
        For col = 0 To data.Columns.Count - 1
            worksheet.Cells(1, col + 1) = data.Columns(col).ColumnName
        Next

        ' Write data
        For row = 0 To data.Rows.Count - 1
            For col = 0 To data.Columns.Count - 1
                worksheet.Cells(row + 2, col + 1) = data.Rows(row)(col)
            Next
        Next

        excelApp.Visible = True

    Catch ex As Exception
        MessageBox.Show($"Excel export failed: {ex.Message}")
    Finally
        ' Release COM objects
        If worksheet IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet)
        End If
        If workbook IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook)
        End If
        If excelApp IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp)
        End If
    End Try
End Sub
vb
' Add COM reference in project
' Tools -> Add Reference -> COM -> Excel Object Library

Imports Excel = Microsoft.Office.Interop.Excel

Public Sub ExportToExcel(data As DataTable)
    Dim excelApp As Excel.Application = Nothing
    Dim workbook As Excel.Workbook = Nothing
    Dim worksheet As Excel.Worksheet = Nothing

    Try
        excelApp = New Excel.Application()
        workbook = excelApp.Workbooks.Add()
        worksheet = CType(workbook.Worksheets(1), Excel.Worksheet)

        ' Write headers
        For col = 0 To data.Columns.Count - 1
            worksheet.Cells(1, col + 1) = data.Columns(col).ColumnName
        Next

        ' Write data
        For row = 0 To data.Rows.Count - 1
            For col = 0 To data.Columns.Count - 1
                worksheet.Cells(row + 2, col + 1) = data.Rows(row)(col)
            Next
        Next

        excelApp.Visible = True

    Catch ex As Exception
        MessageBox.Show($"Excel export failed: {ex.Message}")
    Finally
        ' Release COM objects
        If worksheet IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet)
        End If
        If workbook IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook)
        End If
        If excelApp IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp)
        End If
    End Try
End Sub

Late Binding (No Type Library)

晚期绑定(无类型库)

vb
Imports System.Reflection

Public Sub CreateExcelLateBound()
    Dim excelType As Type = Type.GetTypeFromProgID("Excel.Application")
    If excelType Is Nothing Then
        MessageBox.Show("Excel not installed")
        Return
    End If

    Dim excelApp As Object = Nothing
    Try
        ' Create COM object
        excelApp = Activator.CreateInstance(excelType)

        ' Call methods via reflection
        excelType.InvokeMember("Visible",
            BindingFlags.SetProperty,
            Nothing,
            excelApp,
            New Object() {True})

        Dim workbooks As Object = excelType.InvokeMember("Workbooks",
            BindingFlags.GetProperty,
            Nothing,
            excelApp,
            Nothing)

        ' Add workbook
        workbooks.GetType().InvokeMember("Add",
            BindingFlags.InvokeMethod,
            Nothing,
            workbooks,
            Nothing)

    Finally
        If excelApp IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp)
        End If
    End Try
End Sub
vb
Imports System.Reflection

Public Sub CreateExcelLateBound()
    Dim excelType As Type = Type.GetTypeFromProgID("Excel.Application")
    If excelType Is Nothing Then
        MessageBox.Show("Excel not installed")
        Return
    End If

    Dim excelApp As Object = Nothing
    Try
        ' Create COM object
        excelApp = Activator.CreateInstance(excelType)

        ' Call methods via reflection
        excelType.InvokeMember("Visible",
            BindingFlags.SetProperty,
            Nothing,
            excelApp,
            New Object() {True})

        Dim workbooks As Object = excelType.InvokeMember("Workbooks",
            BindingFlags.GetProperty,
            Nothing,
            excelApp,
            Nothing)

        ' Add workbook
        workbooks.GetType().InvokeMember("Add",
            BindingFlags.InvokeMethod,
            Nothing,
            workbooks,
            Nothing)

    Finally
        If excelApp IsNot Nothing Then
            System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp)
        End If
    End Try
End Sub

COM Object Release Pattern

COM对象释放模式

vb
' ✅ Good: Proper COM object cleanup
Public Sub UseComObject()
    Dim excelApp As Excel.Application = Nothing
    Dim workbook As Excel.Workbook = Nothing

    Try
        excelApp = New Excel.Application()
        workbook = excelApp.Workbooks.Add()
        ' Use objects
    Finally
        ' Release in reverse order of creation
        If workbook IsNot Nothing Then
            workbook.Close(False)
            Marshal.ReleaseComObject(workbook)
            workbook = Nothing
        End If

        If excelApp IsNot Nothing Then
            excelApp.Quit()
            Marshal.ReleaseComObject(excelApp)
            excelApp = Nothing
        End If

        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Try
End Sub

' ❌ Bad: Not releasing COM objects (memory leak)
Dim excelApp = New Excel.Application()
excelApp.Workbooks.Add()
' No cleanup - Excel process remains in memory!
vb
' ✅ Good: Proper COM object cleanup
Public Sub UseComObject()
    Dim excelApp As Excel.Application = Nothing
    Dim workbook As Excel.Workbook = Nothing

    Try
        excelApp = New Excel.Application()
        workbook = excelApp.Workbooks.Add()
        ' Use objects
    Finally
        ' Release in reverse order of creation
        If workbook IsNot Nothing Then
            workbook.Close(False)
            Marshal.ReleaseComObject(workbook)
            workbook = Nothing
        End If

        If excelApp IsNot Nothing Then
            excelApp.Quit()
            Marshal.ReleaseComObject(excelApp)
            excelApp = Nothing
        End If

        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Try
End Sub

' ❌ Bad: Not releasing COM objects (memory leak)
Dim excelApp = New Excel.Application()
excelApp.Workbooks.Add()
' No cleanup - Excel process remains in memory!

Creating COM-Visible .NET Components

创建COM可见的.NET组件

COM-Visible Class

COM可见类

vb
Imports System.Runtime.InteropServices

<ComVisible(True)>
<Guid("12345678-1234-1234-1234-123456789012")>
<ClassInterface(ClassInterfaceType.None)>
<ProgId("MyCompany.Calculator")>
Public Class Calculator
    Implements ICalculator

    Public Function Add(a As Integer, b As Integer) As Integer Implements ICalculator.Add
        Return a + b
    End Function

    Public Function Subtract(a As Integer, b As Integer) As Integer Implements ICalculator.Subtract
        Return a - b
    End Function
End Class

' Interface for COM
<ComVisible(True)>
<Guid("87654321-4321-4321-4321-210987654321")>
<InterfaceType(ComInterfaceType.InterfaceIsDual)>
Public Interface ICalculator
    Function Add(a As Integer, b As Integer) As Integer
    Function Subtract(a As Integer, b As Integer) As Integer
End Interface
vb
Imports System.Runtime.InteropServices

<ComVisible(True)>
<Guid("12345678-1234-1234-1234-123456789012")>
<ClassInterface(ClassInterfaceType.None)>
<ProgId("MyCompany.Calculator")>
Public Class Calculator
    Implements ICalculator

    Public Function Add(a As Integer, b As Integer) As Integer Implements ICalculator.Add
        Return a + b
    End Function

    Public Function Subtract(a As Integer, b As Integer) As Integer Implements ICalculator.Subtract
        Return a - b
    End Function
End Class

' Interface for COM
<ComVisible(True)>
<Guid("87654321-4321-4321-4321-210987654321")>
<InterfaceType(ComInterfaceType.InterfaceIsDual)>
Public Interface ICalculator
    Function Add(a As Integer, b As Integer) As Integer
    Function Subtract(a As Integer, b As Integer) As Integer
End Interface

Register for COM

注册COM组件

bash
undefined
bash
undefined

Register assembly for COM

Register assembly for COM

regasm MyAssembly.dll /tlb /codebase
regasm MyAssembly.dll /tlb /codebase

Unregister

Unregister

regasm MyAssembly.dll /u
regasm MyAssembly.dll /u

Generate type library

Generate type library

tlbexp MyAssembly.dll
undefined
tlbexp MyAssembly.dll
undefined

Legacy VB6 Patterns to Modernize

待现代化的VB6遗留模式

Error Handling

错误处理

vb
' VB6 style (avoid in new code)
Public Function GetCustomer(id As Integer) As Customer
    On Error GoTo ErrorHandler

    ' Code here
    Exit Function

ErrorHandler:
    MsgBox "Error: " & Err.Description
    Resume Next
End Function

' VB.NET modern style
Public Function GetCustomer(id As Integer) As Customer
    Try
        ' Code here
    Catch ex As ArgumentException
        MessageBox.Show($"Invalid argument: {ex.Message}")
        Return Nothing
    Catch ex As Exception
        MessageBox.Show($"Error: {ex.Message}")
        Throw
    End Try
End Function
vb
' VB6 style (avoid in new code)
Public Function GetCustomer(id As Integer) As Customer
    On Error GoTo ErrorHandler

    ' Code here
    Exit Function

ErrorHandler:
    MsgBox "Error: " & Err.Description
    Resume Next
End Function

' VB.NET modern style
Public Function GetCustomer(id As Integer) As Customer
    Try
        ' Code here
    Catch ex As ArgumentException
        MessageBox.Show($"Invalid argument: {ex.Message}")
        Return Nothing
    Catch ex As Exception
        MessageBox.Show($"Error: {ex.Message}")
        Throw
    End Try
End Function

File I/O

文件I/O

vb
' VB6 style (avoid)
Dim fileNum As Integer = FreeFile()
FileOpen(fileNum, "data.txt", OpenMode.Output)
PrintLine(fileNum, "Hello World")
FileClose(fileNum)

' VB.NET modern style
Using writer = New StreamWriter("data.txt")
    writer.WriteLine("Hello World")
End Using

' Or async
Await File.WriteAllTextAsync("data.txt", "Hello World")
vb
' VB6 style (avoid)
Dim fileNum As Integer = FreeFile()
FileOpen(fileNum, "data.txt", OpenMode.Output)
PrintLine(fileNum, "Hello World")
FileClose(fileNum)

' VB.NET modern style
Using writer = New StreamWriter("data.txt")
    writer.WriteLine("Hello World")
End Using

' Or async
Await File.WriteAllTextAsync("data.txt", "Hello World")

Collections

集合

vb
' VB6 Collection (avoid in new code)
Dim customers As New Collection()
customers.Add(customer, "key1")
Dim item = customers("key1")

' VB.NET generic collections
Dim customers = New Dictionary(Of String, Customer)()
customers.Add("key1", customer)
Dim item = customers("key1")

' Or List(Of T)
Dim customerList = New List(Of Customer)()
customerList.Add(customer)
vb
' VB6 Collection (avoid in new code)
Dim customers As New Collection()
customers.Add(customer, "key1")
Dim item = customers("key1")

' VB.NET generic collections
Dim customers = New Dictionary(Of String, Customer)()
customers.Add("key1", customer)
Dim item = customers("key1")

' Or List(Of T)
Dim customerList = New List(Of Customer)()
customerList.Add(customer)

Migration Strategy

迁移策略

Incremental Migration

增量迁移

vb
' 1. Start with COM interop wrapper
' Wrap VB6 COM component in VB.NET

Public Class VB6Wrapper
    Private vb6Component As Object

    Public Sub New()
        vb6Component = CreateObject("VB6Project.Component")
    End Sub

    Public Function ProcessData(data As String) As String
        Return vb6Component.ProcessData(data).ToString()
    End Function
End Class

' 2. Gradually replace with native VB.NET
Public Class ModernComponent
    Public Function ProcessData(data As String) As String
        ' New VB.NET implementation
        Return data.ToUpper()
    End Function
End Class
vb
' 1. Start with COM interop wrapper
' Wrap VB6 COM component in VB.NET

Public Class VB6Wrapper
    Private vb6Component As Object

    Public Sub New()
        vb6Component = CreateObject("VB6Project.Component")
    End Sub

    Public Function ProcessData(data As String) As String
        Return vb6Component.ProcessData(data).ToString()
    End Function
End Class

' 2. Gradually replace with native VB.NET
Public Class ModernComponent
    Public Function ProcessData(data As String) As String
        ' New VB.NET implementation
        Return data.ToUpper()
    End Function
End Class

Best Practices

最佳实践

✅ DO

✅ 推荐做法

vb
' Use modern VB.NET features in new code
Option Strict On
Option Explicit On

' Release COM objects explicitly
Marshal.ReleaseComObject(comObject)
GC.Collect()

' Use Try-Catch instead of On Error
Try
    ' Code
Catch ex As Exception
    ' Handle
End Try

' Use generics instead of Collections
Dim items = New List(Of Customer)()

' Use async for I/O
Await File.WriteAllTextAsync("file.txt", content)
vb
' Use modern VB.NET features in new code
Option Strict On
Option Explicit On

' Release COM objects explicitly
Marshal.ReleaseComObject(comObject)
GC.Collect()

' Use Try-Catch instead of On Error
Try
    ' Code
Catch ex As Exception
    ' Handle
End Try

' Use generics instead of Collections
Dim items = New List(Of Customer)()

' Use async for I/O
Await File.WriteAllTextAsync("file.txt", content)

❌ DON'T

❌ 不推荐做法

vb
' Don't use VB6 compatibility module
Imports Microsoft.VisualBasic.Compatibility.VB6  ' Legacy only!

' Don't use Option Strict Off
Option Strict Off  ' Avoid!

' Don't use On Error in new code
On Error Resume Next  ' VB6 style

' Don't forget to release COM objects
Dim excelApp = New Excel.Application()
' ... (no cleanup - memory leak!)

' Don't use late binding when early binding available
Dim obj = CreateObject("Excel.Application")  ' Use typed reference instead
vb
' Don't use VB6 compatibility module
Imports Microsoft.VisualBasic.Compatibility.VB6  ' Legacy only!

' Don't use Option Strict Off
Option Strict Off  ' Avoid!

' Don't use On Error in new code
On Error Resume Next  ' VB6 style

' Don't forget to release COM objects
Dim excelApp = New Excel.Application()
' ... (no cleanup - memory leak!)

' Don't use late binding when early binding available
Dim obj = CreateObject("Excel.Application")  ' Use typed reference instead

Related Skills

相关技能

  • vb-core: Modern VB.NET patterns
  • vb-winforms: Windows Forms migration
  • vb-database: Database migration strategies
  • vb-core: 现代VB.NET模式
  • vb-winforms: Windows Forms迁移
  • vb-database: 数据库迁移策略