Search code examples
vbatypelib

How to register a type library in VBA


I am trying to register a type library programatically from VBA code, using two variants of a technique found using Google (Subs RegisterTypeLibrary and RegisterTypeLibrary2 below).

The code below crashes with an access violation on the call to LoadTypeLib / LoadTypeLibEx. What am I doing wrong? In case it's relevant, the type library is a TLB file generated from a .NET assembly using tlbexp.

Private Enum RegKind
    RegKind_Default = 0
    RegKind_Register = 1
    RegKind_None = 2
End Enum

Private Declare Function LoadTypeLibEx Lib "oleaut32.dll" ( _
    pFileName As Byte, ByVal RegKind As RegKind, pptlib As Object) As Long
Private Declare Function LoadTypeLib Lib "oleaut32.dll" ( _
    pFileName As Byte, pptlib As Object) As Long
Private Declare Function RegisterTypeLib Lib "oleaut32.dll" ( _
    ByVal ptlib As Object, szFullPath As Byte, _
    szHelpFile As Byte) As Long

Private Sub RegisterTypeLibrary(FileName As String)

    Dim abNullTerminatedFileName() As Byte
    Dim objTypeLib As Object
    Dim lHResult As Long

    abNullTerminatedFileName = FileName & vbNullChar
    lHResult = LoadTypeLib(abNullTerminatedFileName(0), objTypeLib)
    If lHResult <> 0 Then
        Err.Raise lHResult, "LoadTypeLib", "Error registering type library " & FileName
    End If
    lHResult = RegisterTypeLib(objTypeLib, abNullTerminatedFileName(0), 0)
    If lHResult <> 0 Then
        Err.Raise lHResult, "RegisterTypeLib", "Error registering type library " & FileName
    End If
    Exit Sub

End Sub
Private Sub RegisterTypeLibrary2(FileName As String)
    Dim abNullTerminatedFileName() As Byte
    Dim objTypeLib As Object
    Dim lHResult As Long

    abNullTerminatedFileName = FileName & vbNullChar
    lHResult = LoadTypeLibEx(abNullTerminatedFileName(0), ByVal RegKind_Register, objTypeLib)
    If lHResult <> 0 Then
        Err.Raise lHResult, "LoadTypeLibEx", "Error registering type library " & FileName
    End If
End Sub

EDIT

I suspect it is something specific about my type library. I've found a solution which I've posted as an answer below.


Solution

  • I've found a solution, using the code below. Basically, the third parameter to LoadTypeLibEx (ITypeLib** in C/C++) is declared as stdole.IUnknown instead of as Object.

    To do so, I needed to add a reference to stdole32.tlb to the VBA project.

    I suspect there is something about my type library that means it can't be declared as a VB (late-bound) Object.

    I could also have declared the third parameter as Long, but I'm not sure that wouldn't lead to problems with reference counting.

    Private Enum RegKind
        RegKind_Default = 0
        RegKind_Register = 1
        RegKind_None = 2
    End Enum
    
    Private Declare Function LoadTypeLibEx Lib "oleaut32.dll" ( _
        pFileName As Byte, ByVal RegKind As RegKind, pptlib As stdole.IUnknown) As Long
    
    Public Sub RegisterTypeLibrary(FileName As String)
        Dim abNullTerminatedFileName() As Byte
        Dim objTypeLib As stdole.IUnknown
        Dim lHResult As Long
    
        abNullTerminatedFileName = FileName & vbNullChar
        lHResult = LoadTypeLibEx(abNullTerminatedFileName(0), ByVal RegKind_Register, objTypeLib)
        If lHResult <> 0 Then
            Err.Raise lHResult, "LoadTypeLibEx", "Error registering type library " & FileName
        End If
    End Sub