The following code reproduces this error (at least under Windows 8.1):
var type = Type.GetTypeFromProgID("InternetExplorer.Application", true);
dynamic ie = Activator.CreateInstance(type);
ie.Quit(); // this disconnects the COM proxy from the out-of-proc IE object
Marshal.ReleaseComObject(ie); // throws
Apparently, the implementation of ReleaseComObject
is doing something more than calling IUnknown::Release
, when it deals with a COM proxy object. My guess is, it may be calling IRemUnknown::RemRelease
, which returns HRESULT
with an error, so ReleaseComObject
throws, because the out-of-proc object has been already disconnected and destroyed with ie.Quit()
.
Presumably, this behavior was introduced in Windows Server 2012.
The best thing you could probably do is to ignore this specific error:
try
{
Marshal.ReleaseComObject(ie);
}
catch (COMException ex)
{
// I'm getting 0x80010108, rather than 0x800706BA
// The object invoked has disconnected from its clients. (Exception from HRESULT: 0x80010108 (RPC_E_DISCONNECTED)
if ((uint)ex.ErrorCode != 0x80010108)
throw;
}
Updated: this is the expected behavior for an API like Quit
, it doesn't violate any COM rules. The goal of Quit
is to provide an API for explicit shutdown. I believe it uses CoDisconnectObject
internally, as a part of the shutdown process. This disconnects all external proxy references, so the server knows it can shut down safely.
The fact that ReleaseComObject
is still trying to do some stuff after that (like, most likely, calling IUnknown::QueryInterface
on the disconnected proxy) is not a fault of the COM server.