CLR SPY and Customer Debug Probes: The Disconnected Context and Unmarshalable Interface Probes
When managed code interacts with COM objects via RCWs, the CLR handles the COM plumbing for you. An important part of this plumbing involves marshaling wrapped interface pointers across contexts. When a COM interface pointer needs to be marshaled from one context to another, the CLR calls CoMarshalInterface in the original context to marshal the pointer to a stream. If this succeeds, the interface pointer can be unmarshaled from the stream in the new context using CoUnmarshalInterface. If the attempt to marshal the pointer to a stream fails, the CLR doesn’t give up; it simply goes against the COM protocol and uses the raw interface pointer in the new context.
Because this "interface smuggling" could cause undesirable behavior for the COM components in use, the goal of the Disconnected Context and Unmarshalable Interface probes is to warn you about this situation. The reason that there are two probes is that there are two potential causes of failure in this scenario.
For performance reasons, marshaling an interface pointer to a stream is done "lazily" - the stream is only created if and when it’s necessary. This is important for understanding the timing of the messages from these probes. When an interface pointer without a corresponding stream requires unmarshaling, the CLR transitions to the original context, marshals the pointer to a stream, then returns to the original context. In many cases, this is a one-time transition, but if the stream expires (typically after 12 minutes of inactivity), then the CLR will once again transition back to the original context to re-marshal the stream.
If these attempts to transition to the original context fail for any reason, the Disconnected Context probe emits the following warning:
Failed to enter object context. No proxy will be used.
If a context transition succeeds but the call to CoMarshalInterface fails, the Unmarshalable Interface probe emits the following warning:
Component is not marshalable. No proxy will be used.
For example, if the COM object whose interface pointer needs to be marshaled implements IMarshal, CoMarshalInterface invokes the methods of this IMarshal implementation. The CLR is then at the mercy of the COM object to make the marshaling successful.