Read Type Information (Classes & Methods) from COM DLL (5 Viewers)

Josef P.

Well-known member
Local time
Today, 09:55
Joined
Feb 2, 2023
Messages
1,143
A little challenge for Windows API enthusiasts and COM/VBA experts:

Has anyone ever successfully read type library information (e.g., class and method names) from a COM DLL in VBA, using Windows APIs like LoadTypeLibEx?
My attempts to use it without too much effort were unsuccessful.

I came across a potential solution here:
https://www.mrexcel.com/board/threa...nto-a-4-column-long-list.1256225/post-6172844
However, this approach seems overly complex for my use case, so I decided to take a detour and implemented a solution via .NET, which gives me easier access to type information.
The downside of the .NET variant is that it requires a registered COM DLL – which I would prefer to avoid. The goal is to call everything directly from VBA, without additional components.

Has anyone managed to read class names and method signatures directly from a COM DLL in VBA (via ITypeLib / ITypeInfo etc.), ideally as simple string output?
 
I used to use an application that would read methods/properties of com dll's called TypeLibVwr.exe (made by iTripoli)

I found a reference to it here: https://type-library-viewer.updatestar.com/en

but I know nothing about that site, so use at your own risk!

I don't think this will solve your requirement to call everything from VBA however. :(

MS seems to have a built-in Object Viewer - perhaps it can be called via Shell() ?
 
Thanks for the reference to TypeLibVwr, I didn't know it yet.

The code of the .net-dll is not complex.
I would just like to know whether it is possible to use the API in VBA with a manageable amount of effort.
In the Excel example, every method within pptlib/ITypeLib is called via API.

API:
Private Declare PtrSafe Function LoadTypeLibEx Lib "OleAut32" (ByVal szFile As LongPtr, ByVal regkind As Long, ByRef pptlib As IUnknown) As Long
The problem is the parameter pptlib (ITypeLib).

This code works in VBA:
(This only provides the number of classes/interfaces.)
Code:
#If Win64 Then
    Private Const NULL_PTR = 0^
    Private Const PTR_LEN = 8&
#Else
    Private Const NULL_PTR = 0&
    Private Const PTR_LEN = 4&
#End If

Private Declare PtrSafe Function LoadTypeLibEx Lib "OleAut32" (ByVal szFile As LongPtr, ByVal regkind As Long, ByRef pptlib As IUnknown) As Long
Private Declare PtrSafe Function DispCallFunc Lib "oleaut32.dll" (ByVal pvInstance As LongPtr, ByVal offsetinVft As LongPtr, ByVal CallConv As Long, ByVal retTYP As Integer, ByVal paCNT As Long, ByRef paTypes As Integer, ByRef paValues As LongPtr, ByRef retVAR As Variant) As Long
 
Private Sub Test()

   Dim TlbObj As stdole.IUnknown
   Dim LibPath As String
   Dim TlbInfoCount As Long
 
   LibPath = Application.References(1).FullPath
   Debug.Print LibPath
 
   If LoadTypeLibEx(StrPtr(LibPath), 2, TlbObj) <> 0 Then
      Debug.Print "Error LoadTypeLibEx"
      Exit Sub
   End If
 
   Const CC_STDCALL = 4&
   TlbInfoCount = vtblCall(ObjPtr(TlbObj), 3& * PTR_LEN, vbLong, CC_STDCALL) 'ITypeLib::GetTypeInfoCount
 
   Debug.Print "TlbInfoCount: "; TlbInfoCount

End Sub

' From Excel/VBA example:
Private Function vtblCall( _
    ByVal InterfacePointer As LongPtr, _
    ByVal VTableOffset As Long, _
    ByVal FunctionReturnType As Long, _
    ByVal CallConvention As Long, _
    ParamArray FunctionParameters() As Variant _
) As Variant
     
    Dim vParamPtr() As LongPtr

    If InterfacePointer = 0& Or VTableOffset < 0& Then Exit Function
    If Not (FunctionReturnType And &HFFFF0000) = 0& Then Exit Function

    Dim pIndex As Long, pCount As Long
    Dim vParamType() As Integer
    Dim vRtn As Variant, vParams() As Variant

    vParams() = FunctionParameters()
    pCount = Abs(UBound(vParams) - LBound(vParams) + 1&)
    If pCount = 0& Then
        ReDim vParamPtr(0& To 0&)
        ReDim vParamType(0& To 0&)
    Else
        ReDim vParamPtr(0& To pCount - 1&)
        ReDim vParamType(0& To pCount - 1&)
        For pIndex = 0& To pCount - 1&
            vParamPtr(pIndex) = VarPtr(vParams(pIndex))
            vParamType(pIndex) = VarType(vParams(pIndex))
        Next
    End If

    pIndex = DispCallFunc(InterfacePointer, VTableOffset, CallConvention, FunctionReturnType, pCount, vParamType(0&), vParamPtr(0&), vRtn)
    If pIndex = 0& Then
        vtblCall = vRtn
    Else
      Err.Raise vbObjectError, "vtblCall.DispCallFunc", "DispCallFunc return <> 0"
    End If

End Function

For comparison the C# code:
Code:
private enum REGKIND
{
    REGKIND_DEFAULT = 0,
    REGKIND_REGISTER = 1,
    REGKIND_NONE = 2
}

[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
private static extern void LoadTypeLibEx(
    [MarshalAs(UnmanagedType.LPWStr)] string strTypeLibName,
    REGKIND regKind,
    out ITypeLib typeLib);

public string[] ReadTypeLib(string typeLibFilePath)
{
    LoadTypeLibEx(typeLibFilePath, REGKIND.REGKIND_NONE, out ITypeLib typeLib);
    int typeCount = typeLib.GetTypeInfoCount();
    ...


Note: The alternative with TlbInf32.dll is not possible because it is no longer available for 64 bit.
 
Last edited:
Has anyone managed to read class names and method signatures directly from a COM DLL in VBA (via ITypeLib / ITypeInfo etc.), ideally as simple string output?
I tried once quite a while ago. - I didn't have the patience to achieve success.
On first glance, the code on MrExcel looks complex indeed, but I fear this is what is required to make it work with pure VBA/API.
 

Users who are viewing this thread

  • Back
    Top Bottom