日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

进程外COM组件的一个实例

發(fā)布時(shí)間:2024/4/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程外COM组件的一个实例 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

之前寫(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的命令為:
mt.exe -tlb:com.tlb -dll:com.exe -out:com.exe.manifest 對(duì)于產(chǎn)生出來(lái)的manifest,我們需要做一些修改:一是把coclass和com.exe的信息去掉,這一塊我們是自己通過(guò)代碼CreateProcess實(shí)現(xiàn)的,我們需要指定的是tlb文件和其GUID,以及其支持的所有接口(參考代碼中的com.exe.manifest);二是mt.exe 產(chǎn)生的文件默認(rèn)是單行的,為了閱讀方便,需要手工換行。

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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。