如何在Windows中注册COM(组件对象模型)?(用于图标覆盖处理程序)

How to register a COM (Component Object Model) in Windows? (for Icon Overlay Handler)

本文关键字:用于 图标 覆盖 程序 处理 组件对象模型 Windows 注册 COM      更新时间:2023-10-16

我对COM对象非常缺乏经验,以下是我所做的:

  • 在C++中,我创建了一个扩展IUnknow并实现QueryInterface、AddRef和Release的类
  • 扩展IShellIconOverlayIdentifier并实现里面的3个方法
  • 使用__declspec(dllexport)导出类
  • DLL是用MSVC2015 64位编译的。(在windows7 64位上工作)

现在是困难的部分:

如何使窗口链接/使用DLL:

  • https://msdn.microsoft.com/en-us/library/windows/desktop/hh127455(v=vs.85).aspx解释如何注册Overlay处理程序,但不解释如何注册COM对象。我尝试了几次,但在windows重新启动后,什么也没发生

如何注册以及如何检查是否注册了COM dll

是否存在编译器/体系结构之类的编译限制

简化版:

我似乎对COM实现有一个非常不完整的愿景,为了注册COM对象,有两个方向是可能的:

  • 在寄存器中手动注册对象,这简直是一场噩梦
  • 实现DllRegisterServer和DllUnregisterServer:这也是一场噩梦

为了简化问题,我删除了所有其他功能,只有这两个功能:

STDAPI DllRegisterServer(void)
{
return NOERROR;
}
STDAPI DllUnregisterServer(void)
{
return NOERROR;
}

不幸的是,这并没有导出到DLL中(因为没有指定__declspec(dllexport))。一旦我尝试添加此声明,编译器就会抱怨,并且不会生成DLL。

解决方案步骤1:

Olectl.h非常非常糟糕,避免导出DllRegisterServer。

要手动创建COM对象(无需向导),需要以下步骤:

  • 实现DllGetClassObject&DllCanUnloadNow
  • 实现工厂扩展IClassFactory
  • 实现Target类,扩展IUknown
  • 在注册表中注册COM
  • [可选]实现DllRegisterServer&DllUnregisterServer使注册表更容易

实现DllGetClassObject&DllCan立即卸载

这些是唯一导出到DLL函数的:

STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID * ppObject)
STDAPI DllCanUnloadNow(void)

DllGetClassObject,如果提供的rclsidTargetClassCLSIDriid是`FactoryCLSID,则它将创建并返回Factory对象。

如果DLL正在使用中(S_OK),则DllCanUnloadNow返回,在这种情况下,用户/客户端可以卸载DLL(S_FALSE)。

问题是,该定义不允许添加__declspec(dllexport),可能是因为微软的一些单极指令使VS成为"强制性的"。

要导出它们,只需在之前添加即可

#pragma comment( linker, "/export:DllGetClassObject,PRIVATE" )
#pragma comment( linker, "/export:DllCanUnloadNow,PRIVATE" )
//TODO: make this cross-compiler compatible?

实施工厂

实现AddRefRelease:它们维护当前有多少客户端/用户在使用此Factory对象。AddRef将其递增1,Release将其递减1。一旦数字为0,Release就可以自动删除自己。

实现如果riid是FactoryCLSID则返回的QueryInterface

实现CreateInstance,如果riid与TargetClassCLSID 匹配,则返回TargetObject的实例

实现目标类

同样,我们必须实现AddRef、Release和QueryInterface,但这次是针对最后一个类。

在我的例子中,这个Target类扩展了IShellIconOverlayIdentifier。

将COM对象注册到操作系统注册表

生成dll后,需要设置几个注册表。其中一些链接在一起,因此添加一个可能会自动添加另一个。

HKEY_CLASS_ROOT::CLSID::<Add Here>
HKEY_CLASS_ROOT::Wow6432Node::CLSID::<Add Here>
HKEY_LOCAL_MACHINE::SOFTWARE::Classes::CLSID::<Add Here>
HKEY_LOCAL_MACHINE::SOFTWARE::Classes::Wow6432Node::CLSID::<Add Here>
HKEY_LOCAL_MACHINE::SOFTWARE::Wow6432Node::Classes::CLSID::<Add Here>

要添加的内容是:

  • 创建一个密钥:name={TargetClassCLSID},value=<Any app name>
  • 创建一个子密钥:name=InProcServer32,value=<link to your dll>
  • 创建InProcServer32的子字符串:name=ThreadingModel,value=Apartment

//TODO:可能还有其他选择,以更好地理解这意味着什么。

在我的情况下,我不得不为IconHandler:注册更多的寄存器

HKEY_LOCAL_MACHINE::SOFTWARE::Microsoft::Windows::CurrentVersion::Explorer::ShellIconOverlayIdentifier::<Overlay here>
HKEY_LOCAL_MACHINE::SOFTWARE::Microsoft::Windows::CurrentVersion::ShellExtensions::Aproved::<new entry here>

其中覆盖条目是密钥:name=<Any app name>,value=<TargetClassCLSID>

新条目是一个字符串值,名称=<TargetClassCLSID>,值=Any app name

这些值也需要在:中

HKEY_LOCAL_MACHINE::SOFTWARE::Wow6432Node::Microsoft::Windows....