1
votes

I have a native C++ COM object implementing an interface called ILogger. It uses the threading model "Both" and a free threaded marshaller is aggregated.

Using this from .NET all is well unless I use the .NET reference to an ILogger from a different apartment. This leads to the dreaded Unable to cast COM object of type 'System.__ComObject' to interface type ...ILogger exception.

I understand one is not meant to use COM objects from different apartments without marshaling, however, it does seem to work in other cases. In my instance for example there is an Application object that does not use any custom marshaler. I can access it "just fine" from non-STA threads (it's created in the STA). Further, making my logger use NTA rather than MTA (and the default neutral apartment marshaler, so no stubs etc) no exceptions are thrown (that is not entirely accurate, this worked on my machine, however, not once deployed elsewhere).

My question is mainly why can I access objects such as Application from different apartments but I am seeing failures with my free-threaded logger. If .NET marshals in the first instance, why not the second. Furthermore, is there a way to use my logger in another apartment in .NET without creating a new instance that attempts to keep apartment-affinity?

1
Is this what you're looking for?noseratio
I'm looking for the other way round. COM objects in the STA seem to be marshaled by .NET, however, my native COM object that uses the FTM does not seem to get marshaled. I am using registry-free COM.Marcus
Maybe I missed something but I can't reproduce. If I create a C++ ATL project from scratch, add a simple object, select Both, agg FTM, I can use one instance of that object from multiple .NET threads w/o issue, MTA or STA. If I remove the FTM and I create the instance from a .NET MTA thread, it works fine (if I create the instance from a .NET STA, it also works, but of course I have to force message pumping from .NET). To me that's all normal. For a "logger" kind of interface (fire & forget), you shouldn't need FTM anyway. Do you have reproducing bits?Simon Mourier
@Marcus, I understand one is not meant to use COM objects from different apartments without marshaling, however, it does seem to work in other cases... It's simply wrong to rely on this behavior. You really should be using CoMarshal* family of APIs to marshal your object between COM apartments, be it a COM or a .NET object. Refer to INFO: Descriptions and Workings of OLE Threading Models and follow every single rules it talks about.noseratio
I had a bug in my native component that cause QI for IMarshal to fail. This in turn caused .NET to use the default marshaler instead (based on typelib) which would fail in some cases (I think related to missing access rights for writing the registry), and I'm using SxS. .NET does seem to query for IMarshal suggesting that it should be OK to use the RCW from a different apartment as .NET seems to be doing COM marshaling, unless I'm missing something.Marcus

1 Answers