How do I register a COM class in memory?
I have a COM class (for example CLSID_WidgetFactory
) that I want to make available to everyone in my process that calls:
CoCreateInstance(CLSID_Widget, ...);
But I want to make it available unregistered, or include it in the unregistered COM assembly manifest.
The main question
I have:
- a
clsid
(CLSID_Widget
) - a
IClassFactory
implementation
How can I register them with the COM infrastructure so that each of my processes can create a COM object?
Obviously I want to do this:
- without registering a COM object in a piece of registry
HKLM\Software\Classes
- without registering COM object in
HKCU\Software\Classes
hive - do not create unregistered COM assembly manifest
It is clear that I would have a 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 factory class:
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 the COM class in memory:
void RegisterClassFactory(Guid clsid, IClassFactory classfactory)
{
//...
}
Search queries
- How to register a COM object in memory
- How to register a COM class in my process
- How to register CLSID in memory
- How to register IClassFactory in my application
Note . I know the answer. But I can't figure out the right set of search terms that can trigger hits.
Bonus reading
source to share
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 any of your processes can create this arbitrary COM object (although it is not registered in the registry and has not been included in the assembly manifest):
CoCreateInstance(CLSID_Widget, null, CLSCTX_INPROC_SERVER, IID_IUnknown, out unk);
If you are registering multiple classes, you can combine the flag REGCLS_SUSPENDED
(for example with or operator |
):
Suspends registration and activation requests for the specified CLSID until a call to CoResumeClassObjects is made . This is typically used to register 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 SCM call, regardless of how many CLSIDs are registered for the server.
Note This flag prevents COM activation errors from a possible race condition between the application shutdown and the application trying to register the COM class.
and then call CoResumeClassObjects
once to register the classes atomically.
If you intend to do this from a DLL, you must ensure that the DLL provides an entry point for registration at the beginning of the application. Or just don't use resume and pause the functions of the class objects.
source to share
CoRegisterClassObject
will register a factory class for the given one CLSID
and make it available to the callers of your process, however just in the registration apartment (you could probably register in multiple apartments though).
CoCreateInstance
elsewhere in the apartment will be successful, as if CLSID
registered through the registry in the usual way.
AFAIR you're interested in Delphi, but anyway this ATL C ++ class is a sample snippet that shows the use of CoRegisterClassObject
temporarily register CLSID
for a third party CoCreateInstance
in the scope of a local variable:
{
BEGIN_OBJECT_MAP(g_pObjectMap)
OBJECT_ENTRY(__uuidof(CSplitterMediaObject), CSplitterMediaObject)
// ...
END_OBJECT_MAP()
CLocalObjectMap ObjectMap(g_pObjectMap, TRUE);
// ...
// Someone calls CoCreateInstance(__uuidof(CSplitterMediaObject), ...
// here and the call succeeds as if the class is registered
}
source to share