CLR SPY and Customer Debug Probes: The QueryInterface Failure Probe

It has taken awhile, but with this entry I will have described all 11 probes that exist in v1.1 of the CLR.

When an RCW queries its underlying COM object for a specific interface, the QueryInterface call could fail for a variety of reasons.  The QueryInterface Failure probe doesn’t report every failed QI call as you might expect, but it isolates a specific cause of failure: when an interface cannot be marshaled to the current context.  When this happens, this probe emits a warning like the following:

Failed to QI for interface IMyInterface because it does not have a COM proxy stub registered.

To detect this condition, this probe makes the CLR do some extra work after an applicable QueryInterface call fails.  If the failure happens in a different context than the COM object’s original context, the CLR will transition to the original context and try another QueryInterface call.  If this also fails, the CLR does nothing more; the original failure must have been unrelated to the context.  But if it succeeds, then that indicates that the QueryInterface failure is context-specific, so it emits the warning.

There’s one other scenario in which this probe emits a warning: when a QueryInterface call fails in the object’s original context, but the CLR has determined that this COM object is a standard proxy (because the interface pointer’s address is in the range of the loaded ole32.dll).

What can you do about such failures?  You can register an appropriate type library or proxy-stub DLL, depending on the COM component. Or you can take steps to avoid context transitions, such as using the STAThreadAttribute.

Comments (8)

  1. Ries Vriend says:

    Could you elborate a bit on the specific (but so very much real-life) case of accessing a strongly typed COM object reference that is running inside the VB6 debugger from within a .net process (especially an ASP.NET application)? Doing so yields a QI-error, even when using the binary compatibility feature of VB6. Therefore, the ability is lost to step into the VB6 code from inside the ASP.NET application. The only workaround that I know of is to use late binding in VB.NET; but that fails when COM interfaces and events are defined in the VB-components, as well as for C#.
    Support for this scenario would really improve productivity of all of those that have a legacy library of VB components that are re-used from a .net fronted.

  2. Raja says:

    Hi Adam
    I have this problem that I have been trying to solve for long but now I have almost given up. End to my knowledge it seems !

    The problem is this:
    I have developed a MMC Snap-in DLL in C# such that all the MMC COM-interfaces are redefined on .Net-side and given following attributes:

    [   ComImport, 
    Guid("955AB28A-5218-11D0-A985-00C04FD8D565")     ]

    The C# MMC snapin implements IComponent and IComponentData interfaces so that when MMC.exe executes, it can recognize this C# DLL as a COM-exposed Snap-in DLL and loads and displays it correctly in Snap-in console’s left pane.

    IComponentData has an interface-method named Initialize() that is implemented by MySnap-in class and called by MMC at start-up. Inside Initialize(object pUnknown), I initialize an instance member (say, myObject) of the MySnap-in class with the object passed by MMC to the initialize(..) method during start-up. This object is saved as per MMC documentation so that it can be reused later-on to get IConsoleNamespace or any other MMC supported interfaces.

    And here is the problem. When I access this saved object myObject from anywhere within MMC-created-Thread (that is the thread that loads the snapin itself), it works fine . However, when I create a Timer(System.Threading.Timer or System.Timers.Timer) inside MySnapin class and I access myObject within the timer-callback method–I get an exception with the following message:

    QueryInterface for interface IConsoleNamespace2 failed.

    Things I have tried so far but have not worked:
    1) When I WriteLine() ApartmentState for MMC main thread, it gives me STA inside Initialize()
    2) When I WriteLine() ApartmentState for Timer callback method, that thread gives me MTA which is okay as all Timer callbacks are using Threadpool threads and these are MTA by nature.

    3) So with an assumption that it is an Apartment-mismatch, I took out Timer from mySnapin code and created a Thread and specifically set the apartment state to STA, still the Thread-method gives the same error when it accesses the myobject that was saved in Initialize() on MMC thread.

    So I am kind of despondent now. Any help would be really appreciated. Please write to me at if you want any more clarifications regarind this problem.


  3. Read Print says:

    Free books for students, teachers, and the classic enthusiast.

  4. Israel says:

    I have been had this problem for a while… I am trying to find information about this but everybody has not solution…

    Please if anybody have an answer feedback me.



  5. me says:

    Raja : Just have your timer thread create another thread that is STA to do this operation.