I have a legacy C++ "solution engine" that I have already wrapped as an in-process COM object for use by client applications that only require a single "solution engine".
However I now have a client application that requires multiple "solution engines". Unfortunately the underlying legacy code has enough global data, singletons and threading horrors that given available resources it isn't possible to have multiple instances of it in-process simultaneously.
What I am hoping is that some kind soul can tell me of some COM magic where with the flip of a couple of registry settings it is possible to have a separate out-of-process COM server (separate operating system process) for each instance of the COM object requested.
Am I in luck?
Yes, this is possible. The key is to register your coclass by calling CoRegisterClassObject, and OR-in the value REGCLS_SINGLEUSE in the flags
parameter.
If your project is an ATL 7.0+ project, you can do this by overriding CAtlExeModuleT::PreMessageLoop(), which is responsible for registering the class object, thusly:
HRESULT CATLHacksModule::PreMessageLoop(int nShow)
{
HRESULT hr = RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE);
if (hr == S_OK)
{
if (m_bDelayShutdown && !StartMonitor())
{
hr = E_FAIL;
}
}
else
{
m_bDelayShutdown = false;
}
return hr;
}
You would need a "master" coclass to lock in the EXE instance, similar to an "Application" interface. Locate the CoRegisterClassObject() call for its factory. And change the REGCLS argument to REGCLS_SINGLEUSE.
This will automatically unregister the class factory as soon as the first client connects to it. Calling CoCreateInstance() for that factory again starts a new instance of the server. I think.
I'm pretty sure this is not possible. A COM out-of-proc server has to globally register the class objects it provides (via CoRegisterClassObject); part of this registration is the class GUID. Obviously you cannot register the same GUID twice.