如何在内存中注册COM类?

时间:2017-07-27 15:47:50

标签: winapi com

我有一个COM类(例如CLSID_WidgetFactory),我想让我的进程中的任何人都可以调用它:

CoCreateInstance(CLSID_Widget, ...);

但我希望无需注册即可将其提供,或将其包含在免注册的COM程序集清单中。

核心问题

我有:

  • 一个clsidCLSID_Widget
  • IClassFactory实施

如何在COM基础架构中注册这些内容,以便我的进程中的任何人都可以创建COM对象?

显然我想要做到这一点:

从概念上讲,我将拥有我的classID和工厂对象:

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;
   }
}

然后我想注册我的班级工厂:

Guid CLSID_Widget = "{0677445E-EA9B-447A-AF2E-CCD86E49CED0}";
IClassFactory factory = new WidgetFactory();

RegisterClassFactory(CLSID_Widget, factory);

剩下的就是弄清楚如何在内存中注册COM类:

void RegisterClassFactory(Guid clsid, IClassFactory classfactory)
{
   //...
}

搜索字词

  • 如何在内存中注册COM对象
  • 如何在我的流程中注册COM类
  • 如何在内存中注册CLSID
  • 如何在我的应用程序中注册IClassFactory

注意:我知道答案。但我无法弄清楚会触发命中的正确搜索词组。

奖金阅读

2 个答案:

答案 0 :(得分:3)

您可以将CoRegisterClassObjectCLSCTX_INPROC_SERVERREGCLS_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;
}

现在你进程中的任何人都可以创建这个任意的COM对象(即使它没有在注册表中注册,也没有包含在程序集清单中):

CoCreateInstance(CLSID_Widget, null, CLSCTX_INPROC_SERVER, IID_IUnknown, out unk);

如果您要注册多个班级,则可以合并REGCLS_SUSPENDED标记(例如,使用或运算符|):

  

暂停对指定CLSID的注册和激活请求,直到调用CoResumeClassObjects为止。这通常用于为可以注册多个类对象的服务器注册CLSID,以便通过单次调用SCM来减少整体注册时间,从而缩短服务器应用程序启动时间,无论为服务器注册了多少个CLSID

     

注意此标志可防止应用程序关闭和尝试注册COM类的应用程序之间可能存在竞争条件的COM激活错误。

然后调用CoResumeClassObjects一次以原子方式注册类。

如果您打算从DLL执行此操作,则应确保DLL在应用程序启动时提供注册入口点。或者只是不使用简历并暂停类对象功能。

答案 1 :(得分:2)

CoRegisterClassObject会为给定的CLSID注册一个班级工厂,并将其提供给您的流程的来电者,但只是在注册公寓(也许您可以在几个公寓注册)。

公寓内其他地方的

CoCreateInstance会成功,就好像CLSID通过注册表以通常方式注册一样。

AFAIR您对Delphi感兴趣,但无论如何this ATL C ++类是一个示例代码段,显示使用CoRegisterClassObject临时注册CLSID第三方CoCreateInstance在局部变量范围内:

{
        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
}