I have a COM class (e.g., CLSID_WidgetFactory
) that I want to make available to anyone in my process who calls:
CoCreateInstance(CLSID_Widget, ...);
But i want to make it available without having to register it, or include it in a registration-free COM assembly manifest.
I have:
clsid
(CLSID_Widget
)IClassFactory
implementationHow can i register the these with the COM infrastructure so that anyone in my process can create the COM object?
Obviously I want to accomplish this:
HKLM\Software\Classes
registry hiveHKCU\Software\Classes
hiveConceptually i would have my classID, and my factory object:
class WidgetFactory : ComObject, IClassFactory
{
//IClassFactory methods
HRESULT CreateInstance(IUnknown unkOuter, Guid iid, out obj)
{
Widget widget = new Widget();
HRESULT hr = widget.QueryInterface(iid, out obj);
return hr;
}
}
Then i want to register my class factory:
Guid CLSID_Widget = "{0677445E-EA9B-447A-AF2E-CCD86E49CED0}";
IClassFactory factory = new WidgetFactory();
RegisterClassFactory(CLSID_Widget, factory);
All that's left is to figure out how to register a COM Class in-memory:
void RegisterClassFactory(Guid clsid, IClassFactory classfactory)
{
//...
}
Note: I know the answer. But i can't figure out the correct set of search terms that would trigger a hit.
Bonus Reading
You can use CoRegisterClassObject
with CLSCTX_INPROC_SERVER
and REGCLS_MULTIPLEUSE
.
DWORD RegisterClassFactory(Guid clsid, IClassFactory factory)
{
/*
Register a COM class in-memory.
Any requests by COM to create object clsid will use the
class factory given by factory.
This means that a COM object does not have to be registered
in the registry in order to use it. Nor does it have
to be included in an application manifest.
Public domain: No attribution required.
*/
DWORD dwCookie; //returned cookie can be later used to delete the registration
HRESULT hr = CoRegisterClassObject(
clsid, // the CLSID to register
factory, // the factory that can construct the object
CLSCTX_INPROC_SERVER, // can only be used inside our process
REGCLS_MULTIPLEUSE, // it can be created multiple times
out dwCookie // cookie we can later use to delete the registration
);
OleCheck(hr);
return dwCookie;
}
And now anyone in your process can create this arbitrary COM object (even though it isn't registered in the registry, and was not included in an assembly manifest):
CoCreateInstance(CLSID_Widget, null, CLSCTX_INPROC_SERVER, IID_IUnknown, out unk);
If you're registering several classes, you can combine the REGCLS_SUSPENDED
flag (e.g. with the or operator |
):
Suspends registration and activation requests for the specified CLSID until there is a call to CoResumeClassObjects. This is used typically to register the CLSIDs for servers that can register multiple class objects to reduce the overall registration time, and thus the server application startup time, by making a single call to the SCM, no matter how many CLSIDs are registered for the server.
Note This flag prevents COM activation errors from a possible race condition between an application shutting down and that application attempting to register a COM class.
and then call CoResumeClassObjects
once to register the classes atomically.
If you intend to perform this from a DLL, you should make sure the DLL provides an entry point for registration at the start of the application. Or just don't use the resume and suspend class objects functions.