如何在内存中注册 COM 类?

Ian*_*oyd 6 com winapi

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

CoCreateInstance(CLSID_Widget, ...);
Run Code Online (Sandbox Code Playgroud)

但我想使其可用而无需注册,或将其包含在免注册的 COM 程序集清单中。

核心问题

我有:

  • clsid( CLSID_Widget)
  • 一个IClassFactory实现

我如何将这些注册到 COM 基础结构,以便我的进程中的任何人都可以创建 COM 对象?

显然我想完成这个:

  • 无需在HKLM\Software\Classes注册表配置单元中注册 COM 对象
  • 无需在HKCU\Software\Classes配置单元中注册 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;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

RegisterClassFactory(CLSID_Widget, factory);
Run Code Online (Sandbox Code Playgroud)

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

void RegisterClassFactory(Guid clsid, IClassFactory classfactory)
{
   //...
}
Run Code Online (Sandbox Code Playgroud)

搜索词

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

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

奖励阅读

ace*_*ent 4

您可以CoRegisterClassObjectCLSCTX_INPROC_SERVER和 一起使用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;
}
Run Code Online (Sandbox Code Playgroud)

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

CoCreateInstance(CLSID_Widget, null, CLSCTX_INPROC_SERVER, IID_IUnknown, out unk);
Run Code Online (Sandbox Code Playgroud)

如果您要注册多个类,则可以组合该REGCLS_SUSPENDED标志(例如使用 or 运算符|):

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

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

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

如果您打算从 DLL 执行此操作,则应确保 DLL 在应用程序启动时提供注册入口点。或者只是不使用恢复和挂起类对象函数。