进程外COM组件的一个实例
之前寫(xiě)過(guò)一篇使用COM組件的3種方法的文章:啟動(dòng)COM組件的三種機(jī)制,其中后來(lái)補(bǔ)充了一個(gè)用免注冊(cè)的方式使用進(jìn)程外COM組件的方法,因?yàn)橹皇俏淖盅a(bǔ)充,沒(méi)有實(shí)例,可能對(duì)于怎么實(shí)現(xiàn)大家不是很清楚,陸續(xù)收到一些同學(xué)的信,希望能給個(gè)例子。 所以干脆補(bǔ)充一篇,自己也恰好復(fù)習(xí)一下。
步驟大概是這樣的:
我有一個(gè)com.exe的進(jìn)程外com組件,暴露出一個(gè)ITestObject的接口?,F(xiàn)在CustomizedWay.exe要調(diào)用這個(gè)com組件,但不希望通過(guò)注冊(cè)表那一套。 雖然微軟提供了registry-free的com組件機(jī)制,但目前只支持進(jìn)程內(nèi)COM組件(具體參考前文),但由于我們知道一個(gè)COM組件被調(diào)用的來(lái)龍去脈,我們可以跳過(guò)MS那一套,自己來(lái)完成這個(gè)工作 (如果你愿意,寫(xiě)一個(gè)專門針對(duì)registry-free COM的庫(kù)也不是問(wèn)題)。這個(gè)過(guò)程的代碼為:
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));
}
這個(gè)過(guò)程中有幾點(diǎn)需要注意:
- manifest的創(chuàng)建
我們需要?jiǎng)?chuàng)建一個(gè)manifest來(lái)包含接口與tlb的信息,因?yàn)閮蓚€(gè)進(jìn)程間交互的時(shí)候,COM指針是需要marshalling的,而這個(gè)是通過(guò)tlb完成的。創(chuàng)建tlb的命令為:
manifest的集成
然后我們需要將這個(gè)manifest文件嵌入到com.exe和CustomizedWay.exe中,原因是進(jìn)程間通信雙方都需要知道如何marshalling。如果直接使用一下命令:
mt.exe -manifest com.exe.manifest -outputresource:com.exe
mt.exe -manifest com.exe.manifest -outputresource:CustomizedWay.exe 在啟動(dòng)程序時(shí),會(huì)提示找不到:ATL##.dll和MSVCR##.dll,原因在于此處會(huì)把默認(rèn)的manifest內(nèi)容覆蓋掉,而那些內(nèi)容,則包含了MFC,CRt的一些DLL的信息。所以我們需要先merge這兩個(gè)manifest,在嵌入到exe中去(mt.exe -manifest ...),但另外一個(gè)簡(jiǎn)單的方法,就是把com.exe.manifest直接加入到兩個(gè)工程中,這樣在build的時(shí)候,就會(huì)將該manifest的內(nèi)容添加進(jìn)去 - 你可以用VS打開(kāi)exe文件,查看里面的 RT_MANIFEST項(xiàng)。
具體可以下載sample:RegistryFree_COMExe
參考:
- 啟動(dòng)COM組件的三種機(jī)制
- Mt.exe
- Assembly Manifest
總結(jié)
以上是生活随笔為你收集整理的进程外COM组件的一个实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: .在OnPaint()函数和在OnEra
- 下一篇: 敏捷个人第六次练习讨论:个人价值观练习