locked
Aggregating a COM object in .NET using ICustomQueryInterface RRS feed

  • Question

  • Hi,

    I found the blog post "ICustomQueryInterface and CLR V4" by jmstall (http://blogs.msdn.com/b/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspx ) where he describes how to force the CLR to not throw away the "COM callable wrapper" (CCW) in the case where a managed object gets handed a managed object through an unmanaged object.
    The code worked with the Beta versions of .NET 4 but unfortunately does not with the final. The CCW is thrown away and so in the sample code the cast to IFoo2 fails. ICustomQueryInterface.GetInterface() is never called.

    Does any of you have an idea how the code could be fixed so that it works with .NET 4.0 final?

    In case it matters, my scenario is a slightly different: I want to write an Add-In for an unmanaged application. These Add-Ins must implement certain COM interfaces. There already exists an unmanaged Add-In that pretty much does want I want, I only need to change the behavior of a single interface (let's call it IInteresting). So my class only implements IInteresting. All other casts I pipe to an instance of that existing Add-In class using ICustomQueryInterface:

    		CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv)
    		{
    			try
    			{
    				if (iid.Equals(_guidIIntersting))
    				{
    					// This causes our explicit interface implementation to be called:
    					ppv = IntPtr.Zero;
    					return CustomQueryInterfaceResult.NotHandled;
    				}
    
    				if (iid.Equals(_guidIMarshal) || iid.Equals(_guidIManagedObject))
    				{
    					// *** This worked in .NET beta but IMarshal and IManagedObject never make it to 
    					// *** this method in the final.
    					// .Net recognizes that an object is a CCW by testing for IManagedObject. It then throws
    					// away the CCW if our custom feature is used by managed code. We don't want that 
    					// behavior because then ICustomQueryInterface won't be used anymore and our Add-In<br/>
                         // would end up implementing IInteresting only.
    					// So tell the CLR that we don't implement IManagedObject:
    					ppv = IntPtr.Zero;
    					return CustomQueryInterfaceResult.Failed;
    				}
    
    				int result = Marshal.QueryInterface(_existingAddInIntPtr, ref iid, out ppv);
    
    				const int E_NOINTERFACE = -2147467262;
    				if (result == E_NOINTERFACE)
    				{
    					return CustomQueryInterfaceResult.NotHandled;
    				}
    
    				return ppv == IntPtr.Zero ? CustomQueryInterfaceResult.NotHandled : CustomQueryInterfaceResult.Handled;
    			}
    			catch (Exception ex)
    			{
    				System.Diagnostics.Debug.WriteLine(ex.Message);
    				throw;
    			}
    		}
    
    


    This works well and the application uses my Add-In using IInteresting and all the other 15 (or so) interfaces the existing unmanaged Add-In provides. And now to the problem: There are other managed Add-Ins, and if they find my Add-In my ICustomQueryInterface.GetInterface() implementation is not called and so they don't get an RCW for the CCW of my managed Add-In but get my Add-In itself (normal interop behavior), and so for them my object seems to only implement IInteresting. I'd like to force the CLR to hand them an RCW for the CCW of my managed Add-In so that they could transparently cast my Add-In to all the other interfaces.

    I know I could provide a cast operator for each of the interfaces the existing unmanaged object provides but that's not what I want because that Add-In might implement more interfaces in the future and I always would need to add them to my class as well.

    Does any of you have an idea how to make the other managed Add-Ins see all the Interfaces?

    Thursday, July 22, 2010 5:00 PM

All replies

  • Common you Microsoft guys!

    Take the challenge, answer the question, and become heroes! (And give me a reason to continue my MSDN subscription.. ;-))

    Tuesday, August 3, 2010 9:05 AM
  • I'm basically seeing the same problem. I was looking forward to testing my COM stuff through a .NET test project and followed instructions to implement ICustomQueryInterface to fail for queries for the IManagedObject interface but it seems that .NET still sees the returned object as a managed object no matter how many things I tinker with. If somebody has a working example of how to properly use ICustomQueryInterface I would greatly appreciate it. The examples on CodePlex didn't seem to make anything clearer for me.

    Monday, April 2, 2012 6:45 PM
  • Hello,

    Follow the thread below for more help.

    http://stackoverflow.com/questions/1981013/managed-com-aggregation

    Thursday, April 12, 2012 10:25 AM