This will not interest any .NET developers…
One of my customers wanted to create a system-wide singleton COM object hosted in a Windows service. However, the object implementation must be in a DLL. The service should start and create an instance of the object and make it available from other client processes. A simple approach would be to use the RegisterActiveObject function to register that instance as the class moniker of its kind. A client can get a proxy to the same instance by using GetActiveObject. Simple, right? Almost.
If the service is run as a service (and not as a regular EXE server), other clients can’t see the object, as the service needs to run in the local system account, even without the “allow the service to interact with desktop”. In this case, GetActiveObject fails.
The solution is to implement the registration process itself using the little flag ROTFLAGS_ALLOWANYCLIENT when registering with the ROT.
Here’s a sample code to replace RegisterActiveObject: Maybe someone else will find this useful.
HRESULT DoRegisterActiveObject(IUnknown* pUnk, REFCLSID rclsid, DWORD dwFlags, DWORD* pdwRegister) {
CComPtr<IRunningObjectTable> spROT;
CComPtr<IMoniker> spMoniker;
HRESULT hr;
OLECHAR szCLSID[MAX_PATH];
if(!StringFromGUID2(rclsid, szCLSID, (sizeof(szCLSID) / sizeof(szCLSID[0]))))
return E_UNEXPECTED;
if(FAILED(hr = ::GetRunningObjectTable(0, &spROT)))
return hr;
if(SUCCEEDED((hr = CreateItemMoniker(L"!", szCLSID, &spMoniker)))) {
hr = spROT->Register(((dwFlags & ACTIVEOBJECT_WEAK) ? 0 : ROTFLAGS_REGISTRATIONKEEPSALIVE ) | ROTFLAGS_ALLOWANYCLIENT, pUnk, spMoniker, pdwRegister);
}
return hr;
}