进程外COM组件的单实例化和Register-free
来源:互联网 发布:北大软件工程硕士年薪 编辑:程序博客网 时间:2024/05/18 07:14
补充: 可以加入DECLARE_CLASSFACTORY_SINGLETON(xxx) 实现COM组件的单实例化
转载的这篇文章解决了Register-free问题。
之前写过一篇使用COM组件的3种方法的文章:启动COM组件的三种机制,其中后来补充了一个用免注册的方式使用进程外COM组件的方法,因为只是文字补充,没有实例,可能对于怎么实现大家不是很清楚,陆续收到一些同学的信,希望能给个例子。 所以干脆补充一篇,自己也恰好复习一下。
步骤大概是这样的:
我有一个com.exe的进程外com组件,暴露出一个ITestObject的接口。现在CustomizedWay.exe要调用这个com组件,但不希望通过注册表那一套。 虽然微软提供了registry-free的com组件机制,但目前只支持进程内COM组件(具体参考前文),但由于我们知道一个COM组件被调用的来龙去脉,我们可以跳过MS那一套,自己来完成这个工作 (如果你愿意,写一个专门针对registry-free COM的库也不是问题)。这个过程的代码为:
HRESULT CreateMyRemoteHost(ITestObject** ppResult)
{
// Get the COM Server's full path (assume they are in the same folder)
wchar_t file[MAX_PATH] = {0};
if (!GetModuleFileName(NULL, file, MAX_PATH))
return E_FAIL;
wchar_t drive[_MAX_DRIVE] = {0};
wchar_t dir[_MAX_DIR] = {0};
_wsplitpath_s(file, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
_wmakepath_s(file, MAX_PATH, drive, dir, L"Com", L"exe");
// Start process (It will insert its class factory object into a global table held by OS)
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
si.lpReserved = NULL;
si.lpTitle = NULL;
si.lpDesktop = NULL;
si.dwX = si.dwY = si.dwYSize = si.dwXSize = 0;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.lpReserved2 = NULL;
si.cbReserved2 = 0;
BOOL ret = CreateProcess(file, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (!ret) return E_FAIL;
WaitForInputIdle(pi.hProcess, 30000);
// Get class factory (from class table)
CComPtr<IClassFactory> pFactory;
HRESULT hr = CoGetClassObject(CLSID_TestObject, CLSCTX_LOCAL_SERVER, NULL, __uuidof(pFactory), reinterpret_cast<void**>(&pFactory));
if (FAILED(hr)) return hr;
// Query interface by class factory
return pFactory->CreateInstance(NULL, __uuidof(*ppResult), reinterpret_cast<void**>(ppResult));
}
这个过程中有几点需要注意:
- manifest的创建
我们需要创建一个manifest来包含接口与tlb的信息,因为两个进程间交互的时候,COM指针是需要marshalling的,而这个是通过tlb完成的。创建tlb的命令为:mt.exe -tlb:com.tlb -dll:com.exe -out:com.exe.manifest
对于产生出来的manifest,我们需要做一些修改:一是把coclass和com.exe的信息去掉,这一块我们是自己通过代码CreateProcess实现的,我们需要指定的是tlb文件和其GUID,以及其支持的所有接口(参考代码中的com.exe.manifest);二是mt.exe 产生的文件默认是单行的,为了阅读方便,需要手工换行。 - manifest的集成
然后我们需要将这个manifest文件嵌入到com.exe和CustomizedWay.exe中,原因是进程间通信双方都需要知道如何marshalling。如果直接使用一下命令:mt.exe -manifest com.exe.manifest -outputresource:com.exe
在启动程序时,会提示找不到:ATL##.dll和MSVCR##.dll,原因在于此处会把默认的manifest内容覆盖掉,而那些内容,则包含了MFC,CRt的一些DLL的信息。所以我们需要先merge这两个manifest,在嵌入到exe中去(mt.exe -manifest ...),但另外一个简单的方法,就是把com.exe.manifest直接加入到两个工程中,这样在build的时候,就会将该manifest的内容添加进去 - 你可以用VS打开exe文件,查看里面的 RT_MANIFEST项。
mt.exe -manifest com.exe.manifest -outputresource:CustomizedWay.exe
具体可以下载sample:RegistryFree_COMExe
0 0
- 进程外COM组件的单实例化和Register-free
- 进程外COM组件的一个实例
- 如何实现单例的进程内COM组件
- COM/DCOM开发练习之进程外组件实例
- COM/DCOM开发练习之远程进程外组件实例
- COM进程外组件的实现vc++
- 10.COM进程外组件和列集、散集
- com进程内进程外组件
- 用C#编写一个进程外的COM组件
- alt 进程外com组件的连接事件
- 进程外组件免注册COM通信的实现
- 单COM组件的嵌套实现方式
- 多进程下的单实例和全局变量
- COM/DCOM开发练习之进程内组件实例
- COM/DCOM开发练习之进程内组件实例
- 进程内COM组件的创建过程
- COM组件实例创建失败的原因
- 用JavaScript编写COM组件的实例
- Shell脚本的自学之路---开门篇,简单介绍和使用
- CodeForces 471C - MUH and House of Cards(推导)
- C++中的const修饰符
- 空域滤波
- c#垃圾回收机制
- 进程外COM组件的单实例化和Register-free
- 全排列模板
- Fedora使用root账号进行GUI登陆
- iOS开发网络数据之AFNetworking使用 此博文包含图片
- zoj 1298 Domino Effect(最短路径)
- linux查看其他系统信息
- linux shell if 参数
- WEB开发18个错误性总结
- 关于Build Automatically