How can I call a method (COM object) that returns an array of objects from VBScript
I have a COM object 'Foo' that defines a function that returns an array Bar:
public Bar[] Bars()
{
return bars;
}
It's in a DLL that is registered with COM.
I can call it from VBA like this:
Dim aBars() As Bar
aBars = oFoo.Bars()
Dim oBar As Bar
Set oBar = aBars(0)
However, I need to call the same function from VBScript, which has no early binding support, and when I try to do that, it fails:
Dim aBars
aBars = oFoo.Bars()
Dim oBar
Set oBar = aBars(0) ' fails with 'Type Mismatch'
If I check for type "aBars" it is "Unknown ()" and I wonder why it doesn't know what to do with it.
What can I do to make this work?
source to share
There is something wrong with the attributes of the Bar class or the interface, it does not implement IDispatch as a scripting language is required. Only IUnknown, something that VBA can handle, but VBScript cannot. IDispatch is required to support late binding if required for script runtime.
I don't see the Bar at all, so guess. If it is an interface or a class that implements the interface, you need [InterfaceType(ComInterfaceType.InterfaceIsDual)]
to get support for both early and late binding. Or ComInterfaceType.InterfaceIsIDispatch for late binding.
If it's a class, you need [ClassInterface(ClassInterfaceType.AutoDual)]
to get support for early and late times. Or ClassInterfaceType.AutoDispatch for lateness.
Boiler malfunction:
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IBar {
// etc...
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Bar : IBar {
// etc...
}
which supports both early and late binding, and is a good way to hide the implementation details of a class, a strong COM purpose, avoiding the baggage that is retrieved from the base Bar class, System.Object methods.
source to share
You need to return a ComVisible (and enumerable) class , like this:
public Array Bars()
{
return bars;
}
or ArrayList , something like this:
public ArrayList Bars()
{
ArrayList list = new ArrayList();
// etc...
return list;
}
or if you don't like ArrayList, something like this:
public BarList Bars()
{
BarList list = new BarList();
// etc...
return list;
}
[ComVisible(true)]
public class BarList : List<Bar>
{
}
source to share