Casting to a non-default COM interface without using RCW. RRS feed

  • Question

  • Hi,

    The title of this may be a bit misleading, so let me try and explain the problem. Apologies for the length of this.

    I am trying to use an ActiveX exe (we have source, but it's not my code) which implements a kind of publish subscriber interface. I'm using C#.

    There is a method on the ActiveX server to return a particular publisher which implements a COM interfaces called IPublisher. Publishers can be of different types but they all implement the interface IPublisher. For the sake of argument lets call the one I'm trying to get "System" which implements an interface called ISystem, however ISystem is not the default interface. IPublisher has a "GetObject()" method that returns the default COM interface of the publisher.

    What I want to do is make a call to the active exe using the "GetPublisher(string name)" method which will return me the IPublisher interface for "System". I then need to call IPublisher.GetObject() to get the actual System object. Finally I need to cast it to ISystem in order to call the single method I need to call.

    Now I have this all working fine using 2 RCW interop assemblies, one generated from the ActiveX exe which contains the IPublisher interface and one for the System dll containing the ISystem interface. The code looks something like this:

    IPublisher pub = reg.GetPublisher("System");
    ISystem mySystem = (ISystem)pub.GetObject();

    My problem here is that the person who wrote the ISystem interface exposed some methods that use Office which is forcing me to include the office.dll in setup package (I've tried excluding it but it won't go away).

    So I figured I'd convert it to late bound and call it that way, however the "GetObject()" method returns the default instance which is not what I want and I cannot figure out how to get to the ISystem interface.

    I cannot figure out how to cast the object to the correct interface so that my InvokeMember call will work.

    I have tried creating a cut down version of the typelib, and also manually creating a cut down RCW with only the class/method I am interested (so removing the office reference) and it all appears to work find until I call the single method on the ISystem interface which returns null when it should return an object.

    Is there any way I can call QueryInterface or any other way to get to the interface I want without having a reference to an RCW?


    Monday, June 22, 2009 4:20 PM


All replies

  • You could use Marshal.QueryInterface() to get the ISystem pointer.  Making late-bound calls is kinda ugly.  You could decompile the interop assembly with ildasm.exe and hack the IL to get rid of the office dependency.

    Hans Passant.
    Monday, June 22, 2009 6:05 PM
  • Thanks Hans (excuse the late reply). I hadn't realised I could use QueryInterface at the time - although I've used it since with a similar problem.

    In the end I did manage to generate a cut-down type library without the method exposing the MS Office object. I then generated an Interop from that which works fine. I guess that's effectively the same as your second suggestion.
    Monday, September 7, 2009 11:00 AM