如何在Windows中注册COM(组件对象模型)?(用于图标覆盖处理程序)
How to register a COM (Component Object Model) in Windows? (for Icon Overlay Handler)
我对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
- [可选]实现
DllRegisterServe
r&DllUnregisterServer
使注册表更容易
实现DllGetClassObject&DllCan立即卸载
这些是唯一导出到DLL函数的:
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID * ppObject)
STDAPI DllCanUnloadNow(void)
DllGetClassObject,如果提供的rclsid
是TargetClassCLSID
,riid
是`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?
实施工厂
实现AddRef
和Release
:它们维护当前有多少客户端/用户在使用此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....
- 1d 智能指针不适用于语法 (*)++
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 用于访问容器<T>数据成员的正确 API
- 重载操作程序时出错>>用于类中的字符串 memebr
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- C++中的cin.ignore()函数不适用于整个流
- 没有用于初始化C++中的变量模板的匹配构造函数
- 用于C++中带有数组和指针的循环
- 为什么它不适用于Visual 2019的原因
- 使用在用于SFINAE的void_t中具有参数的方法
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- 重载==不适用于二进制树
- Insert函数不适用于2 if语句C++
- 用于矢量处理的多个线程
- 使外部项目可用于find_package CMake
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- C 检索可执行文件的图标,用于Windows注册表图标路径
- Windows/c - 从第三方EXE加载图标,用于SDL_SETWINDOWICON-崩溃
- 如何在Windows中注册COM(组件对象模型)?(用于图标覆盖处理程序)
- 用于确定使用char图标的变化的c++数学计算