Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a VB6 dll using Visual Studio 2015?

I have a windows form application created in Visual Studio.

I have referenced a COM API and I am trying to run this

L_RESULT = Visualfiles.SystemScript("HIST-TEL", sampleVisualBasicColl, "") 

The second parameter needs to bee a collection, so I created this

    Dim sampleVisualBasicColl As New Microsoft.VisualBasic.Collection()

    Dim item1, item2, item3, item4 As String
    item1 = "Items"
    item2 = "In"
    item3 = "A"
    item4 = "Collection"
    sampleVisualBasicColl.Add(item1, "firstkey")
    sampleVisualBasicColl.Add(item2, "secondkey")
    sampleVisualBasicColl.Add(item3, "thirdkey")
    sampleVisualBasicColl.Add(item4, "fourthkey")

But the error that I get is this

Unable to cast object of type 'Microsoft.VisualBasic.Collection' to type 'VBA.Collection'.

I have found this article which I think will help - https://support.microsoft.com/en-gb/kb/323737

But how do I complete steps 1-4?

I have visual studio community 2015 and I am not sure how to create this dll?

Thanks for any advice!

like image 854
danieldunn10 Avatar asked Jan 05 '23 07:01

danieldunn10


1 Answers

The Collection coclass is a chronic trouble-maker, Microsoft created too many implementations of it. And, quite unwisely, gave those implementations the same CLSID. Not that clear how this went so badly wrong, probably one group of programmers not talking to another group. The lousy solution they came up with was to force everybody to apply the [noncreatable] attribute.

Which stops you from adding a reference to, say, vba7.dll so you can create your own Collection object. Which is why the KB article tells you to use VB6 to create an instance of the object. Well, ugh, 18 years is a lot of dog lives and who has VB6 installed anymore today. You need an MSDN license or good luck at an Ebay auction.

Time to get this fixed the correct way instead of that lousy KB way. All you have to do is to create a concrete instance of the Collection object's default interface. By COM rules, the implementation of the interface never matters.

Add a new class to your project and paste this code:

Imports System.Runtime.InteropServices

Namespace VBA    
    <ComVisible(True), Guid("A4C46780-499F-101B-BB78-00AA00383CBB")>
    Public Interface _Collection
        <DispId(0)> Function Item(<[In]> ByRef Index As Object) As Object
        <DispId(1)> Sub Add(<[In]> ByRef Item As Object, ByRef Optional Key As Object = Nothing,
                        ByRef Optional Before As Object = Nothing,
                        ByRef Optional After As Object = Nothing)
        <DispId(2)> Function Count() As Integer
        <DispId(3)> Sub Remove(<[In]> ByRef Index As Object)
        <DispId(-4)> Function _NewEnum() As IEnumerator
    End Interface

    '' <ComVisible(True)>
    <ClassInterface(ClassInterfaceType.None), Guid("A4C4671C-499F-101B-BB78-00AA00383CBB")>
    Public Class Collection
        Implements _Collection
        Private impl As New Microsoft.VisualBasic.Collection

        Public Sub Add(ByRef Item As Object, ByRef Optional Key As Object = Nothing, ByRef Optional Before As Object = Nothing, ByRef Optional After As Object = Nothing) Implements _Collection.Add
            impl.Add(Item, CStr(Key), Before, After)
        End Sub

        Public Sub Remove(ByRef Index As Object) Implements _Collection.Remove
            If TypeOf Index Is String Then impl.Remove(CStr(Index)) Else impl.Remove(CInt(Index))
        End Sub

        Public Function Count() As Integer Implements _Collection.Count
            Return impl.Count
        End Function

        Public Function _NewEnum() As IEnumerator Implements _Collection._NewEnum
            Return impl.GetEnumerator()
        End Function

        Public Function Item(ByRef Index As Object) As Object Implements _Collection.Item
            Return impl(Index)
        End Function
    End Class
End Namespace

So instead of creating a new Collection object, now create a new VBA.Collection object to keep the component happy. I don't have a good way to test it anymore, hope it works.

like image 68
Hans Passant Avatar answered Jan 07 '23 21:01

Hans Passant