none
Why does the "Embed Interop Types" option not generate the appropriate DispIdAttributes in some cases? RRS feed

  • Question

  • I am creating a typelib for an event interface defined in IDL that I'm then using to create a PIA for COM Interop. I reference the PIA in a C# project, set the "Embed Interop Types" setting to true, and hook one of the events on the interface. 

    At runtime, I get the following exception when I try to hook the event:

    System.InvalidOperationException: event invocation for COM objects requires event to be attributed with DispIdAttribute
       at System.Runtime.InteropServices.ComAwareEventInfo.GetDataForComInvocation(EventInfo eventInfo, Guid& sourceIid, Int32& dispid)
       at System.Runtime.InteropServices.ComAwareEventInfo.AddEventHandler(Object target, Delegate handler)

    I think that the IL that is generated for the event interface should contain something like the following in the method declaration:

    .custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 1C 06 00 00 00 00 ) 

    The odd thing is that some of the interfaces defined in the same IDL file do have the DispIdAttributes generated for them in the PIA. 

    What would cause the DispIds to not be generated for an interface? 

    Monday, July 23, 2012 8:42 PM

All replies

  • Hi Jason,

    Welcome to the MSDN Forum.

    Before VS2010, we need to ship the Interop Assembly along with the installation package. VS2010/.NET4.0 introduces a new feature called "No PIA (Primary Interop Assembly)", by setting "Embed Interop Types" to true, we no need to ship the Interop Assembly any longer.

    So if it is already a PIA for COM interop, please set this property to false.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, July 24, 2012 7:41 AM
    Moderator
  • Hi Jason,

    As Mike suggested, please set "Embed Interop Types" to false. It should fix your error.


    Regards, http://shwetamannjain.blogspot.com

    Tuesday, July 24, 2012 2:06 PM
  • Mike, Shweta,

    Thanks for your quick replies. However, neither of you have answered my question:

    Why does the "NoPIA" feature, accomplished through setting "Embed Interop Types" to true, not generate the appropriate DispIdAttributes (example IL provided in the original post) for some COM interfaces?

    Perhaps I should provide a little more background. 

    The product that I'm working on interoperates with some older COM software. In one particular instance, we hook events on a COM object through its connection point interface. In .NET 2.0 we had to create a PIA. However, there was a problem with the "SinkHelper" that was generated by the .NET compiler: it stubbed out the entire event package and every stub gets called when the hooked event is raised. In some cases, it isn't so much of a problem, but in others the parameters that are passed to the stubs have RCW's created for them and there reference count is never decremented via the Marshal.ReleaseComObject method, which is a problem for any of those parameters that require explicit release calls. To work around this, we created our own sink helpers that properly released the parameters in the stubs. You can read more about this issue in the links below (one of the authors refers to the leaked parameter instances as "Ghost RCWs"): 

    http://blogs.msdn.com/b/mshneer/archive/2008/10/18/com-interop-handling-events-has-side-effects.aspx

    http://connect.microsoft.com/VisualStudio/feedback/details/278750/the-com-interop-event-provider-advises-a-new-sink-helper-instance-for-every-event-subscription

    Enter .NET 4.0 and the NoPIA feature. We recently migrated to .NET 4.0 and I was very encouraged to see that we should no longer have to maintain our custom sink helper or deliver PIAs. The following blog post explains why I expected to be able to do this:

    http://blogs.msdn.com/b/mshneer/archive/2008/10/28/better-eventing-support-in-clr-4-0-using-nopia-support.aspx

    The problem is that when I tried this (enabled "Embed Interop Types" and hooked the event directly rather than using our sink helper) I got the exception included in the original post:

    System.InvalidOperationException: event invocation for COM objects requires event to be attributed with DispIdAttribute
       at System.Runtime.InteropServices.ComAwareEventInfo.GetDataForComInvocation(EventInfo eventInfo, Guid& sourceIid, Int32& dispid)
       at System.Runtime.InteropServices.ComAwareEventInfo.AddEventHandler(Object target, Delegate handler)

    I used ILDASM to verify that the DispIdAttributes were not there. I also noticed that some of the other interfaces in the same assembly did have the DispIdAttributes properly applied. This is why I'd like to know what causes them to be generated by the compiler in some cases, but not in others.

    Thanks!




    • Edited by Jason Pike Tuesday, July 24, 2012 3:03 PM
    Tuesday, July 24, 2012 2:57 PM
  • It seems that if the COM event interface is defined in IDL using the 'interface' keyword then, even though the DispIDs are specified, they are not picked up and included in the IL by the compiler. If, however, the event interface is marked as "dual" (not recommended for events), or it is defined using the 'dispinterface' keyword in the IDL file, the compiler will pick up the DispIDs and include them in the generated IL. Can someone confirm if this is the intended behavior?
    Friday, August 3, 2012 5:14 PM
  • Can someone verify whether or not .NET compilers should generate the DispID attributes when a COM object (referenced by C# code via COM Interop) is defined in IDL using the 'interface' keyword? 

    Tuesday, September 11, 2012 1:43 PM