Casting to an interface from a COM library fails on the 16th managed thread within IIS (InvalidCastException, WinRT originate error 0x80040155)

2

I'm posting this mostly for anyone else that hits this weird issue, and if anyone can shed a light on why IIS/Cassini is being a devil.

For the most part, we can successfully cast a Dispatch object defined in ODL as

[ uuid(GUID_FOO) ]
dispinterface IFooDisp
{
    ... properties & methods.
};
[ uuid(GUID_FOO_COCLASS),noncreatable ]
coclass FooDisp
{
    [default] dispinterface IFooDisp;
};

to the following interface

[ uuid(GUID_BAR) ]
interface IBar : IUnknown
{
    ... some methods
}

The above are both implemented in a registered C++ OLE/COM automation DLL, and a typelibrary is used to create an Interop DLL and it's regasm'd.

So In C# we successfully and repeatedly can call

myFoo as IBar

and

(IBar) myFoo

Without any trouble. Until....

We discovered that if we open a web page, go to a URL on the server, close the browser and repeat 16 times (Cassini or IIS), that when the 16th managed thread is created, suddenly the cast fails with an underlying exception of:

    Exception Thrown at 0x75151812 (KernelBase.dll) in My.exe: 
WinRT originate error - 0x80040155 : 'Failed to find proxy registration for IID: {GUID_BAR}.' 

When testing

(myFoo as IBar)!=null

The cast returns null all of a sudden. But the object itself is still valid and can be interrogated, just not casted any more.

Why does it fail on the 16th thread, and work fine beforehand? P.s. everything is set to STA. How do I fix this?

c#
com
interop
cassini
ole-automation

1 Answer

2

I can tell you how to fix it, add oleautomation to the IBar attributes. But I'm not sure why it's necessary.

How did I get there?

Given that error code, I checked the registry, as I know from painful experience, that C# or OLE loves to have interfaces defined in the registry so it knows what to do, rather than using the details of Interops/TLB.

On searching, I discovered that the registry didn't contain GUID_BAR as a key, and thus no proxy/stub details, like all the other interfaces.

Grabbing at straws I thought, what if it just needed the registry key to exist? So I added attributes one by one until the right one pushed the registry settings in, adding oleautomation to the IBar interface attribute did the trick. It suddenly fixed it, no more failures to cast.

But I don't know why C# was working fine up to the 16th managed thread. Each thread has it's own set of objects (no cross thread calls, and a 1:1 mapping of managed to COM threads). In attempting to reproduce this with an automated test, simply creating hundreds of threads and doing similar work does not cause the same failure. It must be something special about IIS.

Maybe the meta data gets cleared and re-gathered? Can someone explain more?

answered on Stack Overflow Dec 4, 2018 by GilesDMiddleton

User contributions licensed under CC BY-SA 3.0