none
COM Interop differences in .Net 1.1 and 2.0 RRS feed

  • Question

  • Hello,

    I have a VB6 application that uses COM component written in the .Net 1.1. Everything worked fine until I converted this component to .Net 2.0. After some debugging I found that application is able to instantiate an object defined in the COM, but then it somehow calls method that it shouldn't and finally crashes. Following record is added to the event log after the app crash:

    Event Type: Error
    Event Source: .NET Runtime 2.0 Error Reporting
    Event Category: None
    Event ID: 1000
    Date:  11/14/2008
    Time:  7:25:31 PM
    User:  N/A
    Computer: COMP
    Description:
    Faulting application myapp.exe, version 5.50.0.12, stamp 4555b8cd, faulting module unknown, version 0.0.0.0, stamp 00000000, debug? 0, fault address 0x001d016c.

    This looks like an unhandled exception, but my latest tests show that it is not. I've created two new projects - one in VS2003, other in VS2008 and added COM interface, which is used by the app and a class with blank realization of the interface. So the only difference between the projects is used framework. As a result when I'm registering COM 1.1 - everithyng works fine, but once I register COM 2.0, application crashes with the same error in the event log. There are can not be any exceptions because all methods are blank.

    The second anomaly occurs if I'm rebuilding vb6 application while COM 2.0 is registered - the application starts working with COM 2.0, but crashes with 1.1. (I'm using regasm with \tlb and \codebase options for COM registration.)

    Are there any differences in .Net 1.1 and .Net 2.0 COM Interop which may lead to the described issue?

    Friday, November 14, 2008 6:57 PM

All replies

  • I think you know a lot has changed between the versions. However, I'd be interested in looking at some code to see if it can be reporducible outside of your machine. Can you create a short but complete program that demonstrates the issue and post it here. For short but complete programs, visit this link before you post.
    http://www.yoda.arachsys.com/csharp/complete.html
    Saturday, November 15, 2008 2:03 PM
  • Unfortunately, I had no luck with a reproducible example yet. So any ideas are still highly appreciated.

    Thanks
    • Edited by andreyr123 Monday, November 17, 2008 5:57 PM
    Monday, November 17, 2008 5:26 PM
  • I've got something interesting... I created two test projects: one in the VS2003 and another in the VS2008. Both of them contains the interface (below) and its implementation.

    Here is my interface:

     

    1 Namespace TestCOM  
    2     <InterfaceType(ComInterfaceType.InterfaceIsDual), _  
    3     ComVisible(True), _  
    4     Guid("BAFB2045-9E4A-412f-B8BE-39738424BC0D")> _  
    5     Public Interface _ISimpleComponent  
    6         <DispId(1)> Function Method1() As String 
    7         <DispId(2)> Function Method2() As String 
    8         <DispId(3)> Function Method3() As String 
    9         <DispId(4)> Event SomeEvent(ByRef value As String)  
    10         <DispId(5)> Function Method4() As String 
    11         <DispId(6)> Function Method5() As String 
    12     End Interface 
    13 End Namespace 
    14  

    The implementation of the interface is following:

    1 Namespace TestCOM  
    2     <Serializable(), _  
    3     ClassInterface(ClassInterfaceType.None), _  
    4     ProgId("TestCOM.SimpleComponent"), _  
    5     Guid("3EE6FFE9-B092-4b13-B4EB-68A725A96D51"), _  
    6     ComVisible(True)> _  
    7     Public Class SimpleComponent  
    8         Implements _ISimpleComponent  
    9  
    10         Public Sub New()  
    11         End Sub 
    12  
    13         Public Function Method1() As String Implements _ISimpleComponent.Method1  
    14             Return "Method1" 
    15         End Function 
    16  
    17         Public Function Method2() As String Implements _ISimpleComponent.Method2  
    18             Return "Method2" 
    19         End Function 
    20  
    21         Public Function Method3() As String Implements _ISimpleComponent.Method3  
    22             Return "Method3" 
    23         End Function 
    24  
    25         Public Function Method4() As String Implements _ISimpleComponent.Method4  
    26             Return "Method4" 
    27         End Function 
    28  
    29         Public Function Method5() As String Implements _ISimpleComponent.Method5  
    30             Return "Method5" 
    31         End Function 
    32  
    33         Public Event SomeEvent(ByRef value As StringImplements _ISimpleComponent.SomeEvent  
    34     End Class 
    35 End Namespace 

    After the projects build and appropriate registration I've decided to compare their IDLs and here is what i've got:

    TestCOM 1.1:

    1     dispinterface _ISimpleComponent  
    2     {  
    3         properties:  
    4         methods:  
    5             [id(0), restricted] void QueryInterface(  
    6                             [in] GUID* riid,   
    7                             [out] void** ppvObj);  
    8             [id(1), restricted] unsigned long AddRef();  
    9             [id(2), restricted] unsigned long Release();  
    10             [id(3), restricted] void GetTypeInfoCount([out] unsigned int* pctinfo);  
    11             [id(4), restricted] void GetTypeInfo(  
    12                             [in] unsigned int itinfo,   
    13                             [in] unsigned long lcid,   
    14                             [out] void** pptinfo);  
    15             [id(5), restricted] void GetIDsOfNames(  
    16                             [in] GUID* riid,   
    17                             [inchar** rgszNames,   
    18                             [in] unsigned int cNames,   
    19                             [in] unsigned long lcid,   
    20                             [out] long* rgdispid);  
    21             [id(6), restricted] void Invoke(  
    22                             [inlong dispidMember,   
    23                             [in] GUID* riid,   
    24                             [in] unsigned long lcid,   
    25                             [in] unsigned short wFlags,   
    26                             [in] DISPPARAMS* pdispparams,   
    27                             [out] VARIANT* pvarResult,   
    28                             [out] EXCEPINFO* pexcepinfo,   
    29                             [out] unsigned int* puArgErr);  
    30             [id(7)] void add_SomeEvent([in] IUnknown* obj);  
    31             [id(8)] void remove_SomeEvent([in] IUnknown* obj);  
    32             [id(9)] BSTR Method1();  
    33             [id(10)] BSTR Method2();  
    34             [id(11)] BSTR Method3();  
    35             [id(12)] BSTR Method4();  
    36             [id(13)] BSTR Method5();  
    37     };  
    38  


    TestCOM 2.0:

    1     dispinterface _ISimpleComponent  
    2     {  
    3         properties:  
    4         methods:  
    5             [id(0), restricted] void QueryInterface(  
    6                             [in] GUID* riid,   
    7                             [out] void** ppvObj);  
    8             [id(1), restricted] unsigned long AddRef();  
    9             [id(2), restricted] unsigned long Release();  
    10             [id(3), restricted] void GetTypeInfoCount([out] unsigned int* pctinfo);  
    11             [id(4), restricted] void GetTypeInfo(  
    12                             [in] unsigned int itinfo,   
    13                             [in] unsigned long lcid,   
    14                             [out] void** pptinfo);  
    15             [id(5), restricted] void GetIDsOfNames(  
    16                             [in] GUID* riid,   
    17                             [inchar** rgszNames,   
    18                             [in] unsigned int cNames,   
    19                             [in] unsigned long lcid,   
    20                             [out] long* rgdispid);  
    21             [id(6), restricted] void Invoke(  
    22                             [inlong dispidMember,   
    23                             [in] GUID* riid,   
    24                             [in] unsigned long lcid,   
    25                             [in] unsigned short wFlags,   
    26                             [in] DISPPARAMS* pdispparams,   
    27                             [out] VARIANT* pvarResult,   
    28                             [out] EXCEPINFO* pexcepinfo,   
    29                             [out] unsigned int* puArgErr);  
    30             [id(7)] BSTR Method1();  
    31             [id(8)] BSTR Method2();  
    32             [id(9)] BSTR Method3();  
    33             [id(10)] void add_SomeEvent([in] IUnknown* obj);  
    34             [id(11)] void remove_SomeEvent([in] IUnknown* obj);  
    35             [id(12)] BSTR Method4();  
    36             [id(13)] BSTR Method5();  
    37     };  
    38  

    So, as you can see the IDs of the methods differ. And therefore when i'm calling Method1 from the vb6 application i'm getting call to Method3 instead.

    Any advice how this can be fixed are highly appreciated.

    Thanks.
     

    Thursday, November 20, 2008 8:08 PM
  • As I understand, the DispID attribute value should be converted to the id attribute in the exported tlb, right? or they are not related? Anyways, no matter how I change DispID values, the exported tlb is always the same. But... id values are getting changed after simple reordering of the interface members. That looks pretty weird for me. 
    Friday, November 21, 2008 1:54 PM
  • Well... I solved my issue by simply moving the event definition to the top of the interface...
    Still interesting, is that normal behaviour?
    Friday, November 21, 2008 4:27 PM
  • I'm not up to speed on it, but in COM, events (aka connection points) are always implemented through a separate interface.  Check out the ComSourceInterfaceAttribute class.
    Hans Passant.
    Friday, November 21, 2008 6:55 PM
    Moderator
  • Thanks for your reply. All I know is that an event declared in COM interface is not used by the vb6 application, but it is necessary for other .Net applications, which uses the interface in a "normal .net way". Perhaps it had to be excluded from the interface, but at the moment I cannot do any breaking changes.


    Saturday, November 22, 2008 12:50 PM