Deanna
Deanna

Reputation: 24283

Instantiating a .Net object that has a VB6 defined COM interface in .Net throws TypeLoadException

I have a COM interface defined in a VB6 COM DLL called IODevice.

Public Sub Connect(ByVal Device As String)
End Sub

Public Sub Disconnect()
End Sub

I have a .Net class that imports and implements this interface.

[ComVisible(true)]
[Guid("92255E76-6C1A-333F-883C-6EE9FD9937BA")]
public class COMInterface : ICIO.IODevice {
    public COMInterface() {
        // Do nothing
    }

    public void Connect(string deviceString) {
        // Do stuff
    }

    public void Disconnect() {
        // Undo stuff
    }
}

This object works well, and can by created in VB6 using CreateObject() and referenced as the IODevice interface.

I am now moving the calling code to .Net and using Activator.CreateInstance.

Type deviceType = Type.GetTypeFromProgID(typeProgID, true);
object instance = Activator.CreateInstance(deviceType);

Again, this code works fine and will instantiate and use any of the VB6 classes that implement IODevice. The problem comes when I try and load the .Net objects that implement that interface.

System.TypeLoadException: Retrieving the COM class factory for component with CLSID {92255E76-6C1A-333F-883C-6EE9FD9937BA} failed due to the following error: 80131522. 
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) 
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) 
   at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) 
   at System.Activator.CreateInstance(Type type, Boolean nonPublic) 
   at System.Activator.CreateInstance(Type type) 
   at iCode.Console.IOEngine.Wrappers.ICIO.IODeviceWrapper.ConnectDevice() 

If I remove the interface from COMInterface then the object can be instantiated fine, but lacks the interface allowing me to use any of its members.

public class COMInterface /*: ICIO.IODevice*/ {

All libraries are set to target x86 and .Net 2, but changing these as no affect on the outcome.
I've also confirmed that the VB6 library hosting the IODevice interface and its interop DLL are in the same folder as the assembly containing COMInterface.

What am I missing, what is it failing to do and how can I create an instance of this object from .Net while keeping the IODevice interface?

(The example code is stripped out of a large code base, but I'll try and create a minimal example.)

Upvotes: 0

Views: 452

Answers (1)

Deanna
Deanna

Reputation: 24283

This is caused by the runtime being unable to resolve type used by the original IODevice interface (in this case, VBA.vbVarType).

When I tried to load the assembly and get the type directly with reflection, I received this exception:

System.TypeLoadException: Method 'get_PortType' in type 'NetLibrary.COMInterface' does not have an implementation.
   at System.Reflection.Assembly._GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at System.Reflection.Assembly.GetType(String name)
   at InstantiationTest.Program.Main(String[] args)

Adding a COM reference to msvbvm60.dll allowed this type to be loaded directly, and in turn, the original code was able to create an instance of the object.

Upvotes: 2

Related Questions