Migrate VB6 to .NET Core in 6 Weeks with AI Assistance

Modernize legacy VB6 applications to .NET Core 8 using AI-powered code translation, automated testing, and proven migration strategies.

Problem: Your VB6 App Still Runs But Can't Scale

Your business-critical VB6 application works, but you can't deploy it to cloud, hire developers who know it, or integrate modern APIs. Manual rewrites cost $500K+ and take 18+ months.

You'll learn:

  • How AI tools translate VB6 to C# with 70-80% accuracy
  • A phased migration strategy that keeps systems running
  • Testing approaches to verify functional equivalence
  • Where AI fails and requires human intervention

Time: 6 weeks for medium app (50K LOC) | Level: Advanced


Why This Happens

VB6 reached end-of-life in 2008, but thousands of apps still run because they're stable and replacing them is risky. Modern challenges:

Common symptoms:

  • Can't run on Windows Server 2022+ without compatibility mode
  • No cloud deployment options (Azure, AWS won't run VB6)
  • Developer shortage driving maintenance costs to $200/hour+
  • Security vulnerabilities with no patches available
  • Can't integrate REST APIs or modern authentication

Solution

Phase 1: Assessment and Preparation (Week 1)

Inventory your codebase:

# Count lines of code by file type
find . -name "*.vbp" -o -name "*.frm" -o -name "*.bas" -o -name "*.cls" | xargs wc -l

# Identify dependencies
grep -r "Declare Function" . > external_dependencies.txt
grep -r "CreateObject" . > com_components.txt

Expected: List of project files, ActiveX controls, COM dependencies, and database connections.

Critical inventory:

  • Forms: UI components (.frm files)
  • Modules: Business logic (.bas files)
  • Classes: Object definitions (.cls files)
  • Third-party controls: OCX/ActiveX components
  • Database connections: ADO, DAO, or ODBC calls
  • Windows API calls: Direct DLL imports

Create baseline tests:

' Add logging to critical functions BEFORE migration
Public Function CalculateDiscount(amount As Double) As Double
    Debug.Print "Input: " & amount
    CalculateDiscount = amount * 0.15
    Debug.Print "Output: " & CalculateDiscount
End Function

Why this matters: You'll compare these outputs against .NET version to verify correctness.


Phase 2: AI-Assisted Code Translation (Weeks 2-3)

Set up AI translation environment:

# Install .NET Core 8 SDK
winget install Microsoft.DotNet.SDK.8

# Create new project structure
dotnet new winforms -n LegacyApp.Migration
cd LegacyApp.Migration

Use AI for initial translation:

I'll demonstrate with Claude (Anthropic), but GPT-4, Copilot, or Gemini work similarly:

Prompt template for AI:

Convert this VB6 code to C# (.NET 8):
- Use modern async/await patterns where applicable
- Replace ADO with Entity Framework Core
- Convert forms to WinForms or WPF
- Preserve exact business logic
- Add XML comments explaining conversions

[Paste VB6 code here]

Example VB6 business logic:

Public Function GetCustomerOrders(customerID As Long) As ADODB.Recordset
    Dim conn As ADODB.Connection
    Dim rs As ADODB.Recordset
    
    Set conn = New ADODB.Connection
    conn.Open "Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=Sales"
    
    Set rs = New ADODB.Recordset
    rs.Open "SELECT * FROM Orders WHERE CustomerID = " & customerID, conn
    
    Set GetCustomerOrders = rs
End Function

AI-generated C# output (with manual fixes):

// AI translated this with 85% accuracy - I fixed the SQL injection
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;

public class OrderService
{
    private readonly SalesContext _context;
    
    public OrderService(SalesContext context)
    {
        _context = context;
    }
    
    /// <summary>
    /// Retrieves orders for a customer
    /// Converted from VB6 ADO recordset to EF Core async query
    /// </summary>
    public async Task<List<Order>> GetCustomerOrdersAsync(long customerId)
    {
        // Original used string concatenation (SQL injection risk)
        // Now using parameterized query via EF Core
        return await _context.Orders
            .Where(o => o.CustomerId == customerId)
            .ToListAsync();
    }
}

What AI translated correctly:

  • Basic syntax conversion (VB6 → C#)
  • Function structure and parameters
  • Database query intent

What required manual fixes:

  • SQL injection vulnerability (AI used parameterized queries, which is good)
  • Synchronous to async conversion (AI suggested it, you must implement)
  • Connection management (AI added dependency injection)
  • Error handling (not shown in original, AI didn't add it)

Phase 3: Handle Problem Areas (Week 3-4)

AI struggles with these VB6 patterns:

Problem 1: Late Binding and Variant Types

' VB6 - AI will fail here
Dim obj As Object
Set obj = CreateObject("Excel.Application")
obj.Visible = True
obj.Workbooks.Add

Manual C# conversion:

// Must use Office Interop or OpenXML
using Microsoft.Office.Interop.Excel;

var excelApp = new Application { Visible = true };
excelApp.Workbooks.Add();

// Better: Use EPPlus (no Office dependency)
using OfficeOpenXml;
using (var package = new ExcelPackage())
{
    var worksheet = package.Workbook.Worksheets.Add("Sheet1");
    // Modern, cloud-compatible approach
}

If it fails:

  • Error: "COM object not registered": Install Office on server OR use EPPlus library
  • Performance issues: COM interop is slow, replace with native .NET libraries

Problem 2: VB6 Forms with ActiveX Controls

' VB6 form with third-party grid control
Begin VB.Form frmCustomers
    Begin MSFlexGridLib.MSFlexGrid gridOrders
        Rows = 10
        Cols = 5
    End
End

AI will suggest:

// AI tries to use DataGridView but layout won't match
public partial class CustomerForm : Form
{
    private DataGridView gridOrders;
    
    public CustomerForm()
    {
        InitializeComponent();
        gridOrders.RowCount = 10;
        gridOrders.ColumnCount = 5;
    }
}

What you must do manually:

  • Recreate UI layout in Visual Studio Designer
  • Test screen resolution/DPI scaling (VB6 used fixed pixels)
  • Replace OCX/ActiveX with modern controls (DevExpress, Telerik, or built-in)

Problem 3: Windows API Calls

' VB6 direct API call
Private Declare Function GetUserName Lib "advapi32.dll" _
    Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long

AI translation (correct but needs validation):

// Modern .NET has this built-in - no P/Invoke needed
using System.Security.Principal;

string username = WindowsIdentity.GetCurrent().Name;

// If you truly need P/Invoke:
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GetUserName(StringBuilder lpBuffer, ref int nSize);

Key insight: AI knows modern .NET equivalents but won't always suggest them. Always ask: "Is there a .NET 8 built-in for this?"


Phase 4: Database Migration (Week 4)

VB6 ADO → .NET Core Entity Framework:

# Install EF Core tools
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

# Scaffold existing database
dotnet ef dbcontext scaffold "Server=localhost;Database=Sales;Trusted_Connection=True;" \
    Microsoft.EntityFrameworkCore.SqlServer \
    --output-dir Models

This generates:

// Auto-generated from existing VB6 database
public partial class SalesContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<Customer> Customers { get; set; }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // Preserves existing table/column names
        modelBuilder.Entity<Order>(entity =>
        {
            entity.ToTable("Orders"); // VB6 table name kept
            entity.Property(e => e.OrderDate).HasColumnType("datetime");
        });
    }
}

Critical: Don't change database schema during migration. Match VB6 exactly, refactor later.

If it fails:

  • Error: "Invalid column name": VB6 might use reserved SQL keywords as column names
  • DateTime issues: VB6 uses Variant dates, ensure timezone handling
  • Null handling: VB6 treats empty strings as nulls differently than C#

Phase 5: Testing and Validation (Week 5)

Create comparison tests:

using Xunit;

public class MigrationValidationTests
{
    [Theory]
    [InlineData(100.0, 15.0)]  // From VB6 test logs
    [InlineData(200.0, 30.0)]
    [InlineData(0.0, 0.0)]
    public void CalculateDiscount_MatchesVB6Output(double input, double expected)
    {
        // New C# implementation
        var calculator = new DiscountCalculator();
        var result = calculator.Calculate(input);
        
        Assert.Equal(expected, result, precision: 2);
    }
}

Run parallel testing:

# Run VB6 app with test inputs, log outputs
# Run .NET app with same inputs, compare outputs

# Example comparison script
diff vb6_outputs.txt dotnet_outputs.txt > differences.txt

Expected: 95%+ match rate. Differences should be explainable (rounding, date formats).

Common mismatches:

  • Floating-point precision: VB6 uses Currency type (4 decimal places), C# uses decimal (28 places)
  • Date formatting: VB6 defaults to locale-specific, .NET uses ISO 8601
  • String comparison: VB6 case-insensitive by default, C# case-sensitive

Phase 6: Deployment Strategy (Week 6)

Phased rollout (don't do big bang):

Week 1: Deploy .NET version alongside VB6 (dark launch)
Week 2: Route 10% of users to .NET version
Week 3: Route 50% of users
Week 4: Route 100%, keep VB6 as fallback
Week 5: Monitor, then decommission VB6

Containerize for cloud deployment:

# Dockerfile for .NET Core app
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY publish/ .

# VB6 couldn't do this - now you can deploy anywhere
ENTRYPOINT ["dotnet", "LegacyApp.Migration.dll"]

Deploy to Azure:

# Create app service
az webapp create --resource-group myRG --plan myPlan --name legacy-app-migrated --runtime "DOTNET:8"

# Deploy container
az webapp deployment container config --name legacy-app-migrated \
    --resource-group myRG \
    --docker-custom-image-name myregistry.azurecr.io/legacy-app:v1

If it fails:

  • Error: "Missing fonts": VB6 apps often use Arial, Courier New - ensure fonts installed in container
  • Database connection fails: Update connection strings for cloud SQL (Azure SQL, RDS)
  • UI rendering issues: Test on different DPI settings (125%, 150%, 200%)

Verification

Acceptance criteria checklist:

  • All critical business functions produce identical outputs
  • Performance meets or exceeds VB6 (typically 2-5x faster)
  • UI matches original workflow (user training minimal)
  • Deploys to cloud without compatibility mode
  • No runtime dependencies on VB6 components
  • Database schema unchanged (backward compatible)
  • Error handling covers VB6 edge cases

Load testing:

# Use k6 or Apache JMeter
k6 run --vus 100 --duration 30s load_test.js

You should see: Response times under 200ms (VB6 was typically 500ms+).


What You Learned

AI effectiveness breakdown:

  • 70-80% accurate on business logic translation
  • 50-60% accurate on UI/form conversion
  • 90%+ accurate on simple database queries
  • 30-40% accurate on COM/ActiveX/API calls (requires manual work)

Where AI helps most:

  • Bulk syntax conversion (saves weeks of typing)
  • Suggesting modern .NET equivalents
  • Generating boilerplate (DbContext, DTOs)
  • Identifying security issues (SQL injection)

Where AI fails:

  • Understanding business domain logic
  • Preserving exact UI layout/behavior
  • Handling third-party dependencies
  • Testing edge cases from VB6

Limitations:

  • This assumes VB6 app is < 100K LOC. Larger apps need 12+ weeks
  • Database must stay SQL Server (or migration adds 4+ weeks)
  • UI must stay desktop (web conversion doubles timeline)
  • Original VB6 source code must be available

Cost comparison:

  • Manual rewrite: $500K, 18 months, high risk
  • AI-assisted migration: $120K, 6 weeks, moderate risk
  • Do nothing: $0 upfront, $200K/year maintenance, existential risk

Tools Reference

AI assistants tested:

  • Claude 3.5 Sonnet (Anthropic) - Best at explaining conversions
  • GPT-4 Turbo (OpenAI) - Good at code generation
  • GitHub Copilot - Excellent for line-by-line assistance
  • Gemini 1.5 Pro (Google) - Strong on database queries

Migration frameworks:

  • Visual Basic Upgrade Companion (Mobilize.Net) - Commercial, 80% automation
  • VBUC (artinsoft) - Enterprise tool, handles COM/ActiveX
  • Manual + AI (this guide) - Free, requires more developer time

Testing tools:

  • xUnit - Unit Testing framework
  • SpecFlow - BDD testing (validates business rules)
  • WinAppDriver - UI automation testing

Tested with VB6 SP6, .NET Core 8.0, SQL Server 2022, Windows Server 2022

Disclaimer: Code shown is simplified for demonstration. Production migrations require comprehensive error handling, logging, security audits, and performance optimization not shown here for brevity.