Skip to main content
skill CX Codex

vb6-legacy — Claude Code skill for VB6 and COM interop

A skill for classic VB6 work: how to port code to VB.NET and call COM objects without leaking processes.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add bobmatnyc/claude-mpm-skills --skill vb6-legacy -a claude-code
Open on GitHub

What vb6-legacy does

The skill gathers what you would otherwise dig out of old forum threads: VB6 versus VB.NET differences, COM interop patterns, and the usual migration traps. The code samples cover Variant against strong typing with Option Strict On, ByRef as the default against ByVal, On Error against Try-Catch, and control arrays against List(Of TextBox).

A separate section handles COM from VB.NET. Early binding through a type library reference, late binding through Type.GetTypeFromProgID with reflection calls. There is a release pattern too: Marshal.ReleaseComObject in reverse creation order, then GC.Collect. Skip it and the Excel process stays in memory, so this is worth checking if you export to Excel anywhere.

The skill also shows how to expose a .NET component to COM: ComVisible, Guid and ProgId attributes, an interface marked InterfaceIsDual, and registration with regasm using /tlb and /codebase. You do not invoke it yourself — the model pulls it in when VB6 or COM shows up in a task.

What it helps with

  • move error handling from On Error to Try-Catch
  • find out why an Excel process lingers after export
  • pick between early and late COM binding
  • swap control arrays for collections in VB.NET
  • expose a .NET class to existing COM callers

Example prompts for the agent

  • port this module from VB6 to VB.NET, start with the error handling
  • why does EXCEL.EXE stay in Task Manager after my export runs
  • make this class COM-visible and show me how to register it

How to install vb6-legacy

1Skills CLI (Vercel)

npx skills add bobmatnyc/claude-mpm-skills --skill vb6-legacy -a claude-code

2Manually: put the files in place

~/.claude/skills/vb6-legacy/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/vb6-legacy/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about vb6-legacy

How do I install vb6-legacy in Claude?

Run npx skills add bobmatnyc/claude-mpm-skills --skill vb6-legacy -a claude-code. The skill lands at ~/.claude/skills/vb6-legacy/SKILL.md.

What does vb6-legacy do?

It gives the agent classic VB6 patterns, COM interop examples from VB.NET, and notes on common problems when migrating to VB.NET.

Do I invoke the skill manually?

No. It carries user-invocable: false and disable-model-invocation: true, so the model loads it on its own when VB6 or COM appears in a task.

Source text

SKILL.md · MIT
---
name: vb6-legacy
description: Classic VB6 patterns, COM interop, migration strategies
user-invocable: false
disable-model-invocation: true
version: 1.0.0
category: toolchain
author: Claude MPM Team
license: MIT
tags: [visualbasic, vb6, legacy, com, interop, migration]
---

# VB6 Legacy and COM Interop

Patterns for maintaining VB6 code and strategies for migrating to VB.NET with COM interop.

## VB6 to VB.NET Migration

### 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
```

### 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()
```

## COM Interop from VB.NET

### 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
```

### 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
```

### COM Object Release Pattern

```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-Visible Class

```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

```bash
# Register assembly for COM
regasm MyAssembly.dll /tlb /codebase

# Unregister
regasm MyAssembly.dll /u

# Generate type library
tlbexp MyAssembly.dll
```

## Legacy VB6 Patterns to Modernize

### 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
```

### File 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")
```

### 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)
```

## 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
```

## 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)
```

### ❌ 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
```

## Related Skills

- **vb-core**: Modern VB.NET patterns
- **vb-winforms**: Windows Forms migration
- **vb-database**: Database migration strategies

© Claude MPM Team · MIT · bobmatnyc/claude-mpm-skills

Similar skills

All skills for Programming languages →

From the same set73

ecto-patterns A skill that feeds your agent Ecto conventions for Phoenix apps: schemas, changesets, migrations, transactions and multi-tenancy. CX Codex +1 336installs media-transcoding A skill for batch video transcoding with FFmpeg presets aimed at web, mobile and archive output. Useful when a media library needs one consistent format. CX Codex +1 335installs phoenix-ops A skill for getting a Phoenix app ready for production: releases, runtime config, clustering, telemetry and endpoint hardening. CX Codex +1 331installs pre-merge A checklist skill that runs types, lint and tests before commit, before the PR and before merging to main. Useful when you would rather not find breakage during review. CX Codex +1 330installs vercel-overview A reference skill for the Vercel platform: projects, CLI, environment variables, Git integration, REST API and webhooks. Useful when an agent plans a deploy or digs into project settings. CX Codex +1 328installs vercel-security-access A reference skill for Vercel security: roles, SSO, deployment protection, firewall, BotID and audit logs. Useful when you lock down projects and previews. CX Codex +1 328installs digitalocean-teams A reference skill for DigitalOcean Teams and Organizations: roles, access, membership and consolidated billing. Useful when you set up a team or untangle permissions. CX Codex +1 318installs vercel-storage-data Tells the agent which Vercel service fits your data: Postgres, Redis, Blob, Edge Config or the data cache. CX Codex +1 315installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor