總結一下在VC中呼叫COM元件的方法+++VC呼叫遠端COM+元件
總結一下在VC中呼叫COM元件的方法
準備及條件:
COM伺服器為程序內伺服器,DLL名為simpCOM.dll,該元件只有一個介面IFoo,該介面只有一個方法HRESULT SayHello(void)
在SDK中呼叫
=====================================
一、最簡單最常用的一種,用#import匯入型別庫,利用VC提供的智慧指標包裝類
演示程式碼:
#import "D:\Temp\vc\simpCOM\Debug\simpCOM.dll" no_namespace
CoInitialize(NULL);
IFooPtr spFoo = NULL;
spFoo.CreateInstance(__uuidof(Foo));
spFoo->SayHello();
spFoo.Release();/*暈死了,本來智慧指標就是為了讓使用者不用關心這個的,可是我發現如果不手工呼叫一下的話,程式退出後會發生記憶體訪問錯誤,我是在console中做試驗的,哪位大俠知道怎麼回事請一定指教*/
CoUninitialize();
二、引入midl.exe產生的*.h,*_i.c檔案,利用CoCreateInstance函式來呼叫
演示程式碼:
/*在工程中加入*_i.c檔案,例如本例的simpCOM_i.c,該檔案定義了類和介面的guid值,如果不引入的話,會發生連線錯誤。*/
#include "D:\Temp\vc\simpCOM\simpCOM.h"
CoInitialize(NULL);
IFoo* pFoo = NULL;
HRESULT hr = CoCreateInstance(CLSID_Foo, NULL, CLSCTX_ALL, IID_IFoo, (void**)&pFoo);
if (SUCCEEDED(hr) && (pFoo != NULL))
{
pFoo->SayHello();
pFoo->Release();
}
CoUninitialize();
三、不用CoCreateInstance,直接用CoGetClassObejct得到類廠物件介面,然後用該介面的方法CreateInstance來生成例項。
演示程式碼:
/*前期準備如二方法所述*/
IClassFactory* pcf = NULL;
HRESULT hr = CoGetClassObject(CLSID_Foo, CLSCTX_ALL, NULL, IID_IClassFactory, (void**)&pcf);
if (SUCCEEDED(hr) && (pcf != NULL))
{
IFoo* pFoo = NULL;
hr = pcf->CreateInstance(NULL, IID_IFoo, (void**)&pFoo);
if (SUCCEEDED(hr) && (pFoo != NULL))
{
pFoo->SayHello();
pFoo->Release();
}
pcf->Release();
}
四、不用CoCreateInstance or CoGetClassObject,直接從dll中得到DllGetClassObject,接著生成類物件及類例項(本方法適合於你想用某個元件,卻不想在登錄檔中註冊該元件)
演示程式碼:
/*前期準備工作如二方法所述,事實上只要得到CLSID和IID的定義及介面的定義就行*/
typedef HRESULT (__stdcall * pfnGCO) (REFCLSID, REFIID, void**);
pfnGCO fnGCO = NULL;
HINSTANCE hdllInst = LoadLibrary("D:\\Temp\\vc\\simpCOM\\Debug\\simpCOM.dll");
fnGCO = (pfnGCO)GetProcAddress(hdllInst, "DllGetClassObject");
if (fnGCO != 0)
{
IClassFactory* pcf = NULL;
HRESULT hr=(fnGCO)(CLSID_Foo, IID_IClassFactory, (void**)&pcf);
if (SUCCEEDED(hr) && (pcf != NULL))
{
IFoo* pFoo = NULL;
hr = pcf->CreateInstance(NULL, IID_IFoo, (void**)&pFoo);
if (SUCCEEDED(hr) && (pFoo != NULL))
{
pFoo->SayHello();
pFoo->Release();
}
pcf->Release();
}
}
FreeLibrary(hdllInst);
在MFC中呼叫
=====================================
在MFC中除了上面的幾種方法外,還有一種更方便的方法,就是通過ClassWizard利用型別庫生成包裝類,不過有個前提就是com元件的介面必須是派生自IDispatch
具體方法:
1、按Ctrl+W調出類嚮導,按Add Class按鈕彈出新選單,選From a type libarary,然後定位到simpCOM.dll,接下來會出來該simpCOM中的所有介面,選擇你想生成的介面包裝類後,嚮導會自動生成相應的.cpp和.h檔案.
這樣你就可以在你的MFC工程中像使用普通類那樣使用COM元件了.
演示程式碼:
CoInitialize(NULL);
IFoo foo;
if (foo.CreateDispatch("simpCOM.Foo") != 0)
{
foo.SayHello();
foo.ReleaseDispatch();
}
CoUninitialize();
―――――――――――――――――――――――――――――――――――――――
不好意思,不小心發出去了。
_foo,我覺得不一定要呼叫Release,估計原因是因為spFoo智慧指標物件在CoUninitialize()函式以後呼叫引起的。要是如下面這樣呼叫,應該就沒有問題了。
#import "D:\Temp\vc\simpCOM\Debug\simpCOM.dll" no_namespace
CoInitialize(NULL);
{
IFooPtr spFoo = NULL;
spFoo.CreateInstance(__uuidof(Foo));
spFoo->SayHello();
}
CoUninitialize();
VC呼叫遠端COM+元件
用VB6嚮導做成COM+,並在伺服器上安裝,部分程式碼如下:(名稱為ADOMTS)
Public Function GetADORecordset() As ADOR.Recordset
Dim rsset As ADODB.Recordset
Dim cn As ADODB.Connection
Dim connectstring As String
Dim anerror As ADODB.Error
Dim Sql As String
On Error GoTo rt
connectstring = "Driver={SQL SERVER};Server=192.168.1.123;Database=pubs;UID=sa;"
Sql = "SELECT * FROM authors;"
Set cn = New ADODB.Connection
cn.ConnectionString = connectstring
cn.CursorLocation = adUseClient
cn.Open
Set rsset = cn.Execute(Sql)
Set GetADORecordset = rsset
Exit Function
rt:
For Each anerror In cn.Errors
Debug.Print anerror.Number & ": " & anerror.Description & " - " & anerror.SQLState
Next anerror
End Function
然後用VC6封裝DLL(工程名為connect),遠端呼叫COM+元件(將伺服器上的元件匯出並在客戶端上安裝)。利用VC MFC
CLASSWIZARD新增新類,import from type library,將ADOMTS.tlb新增進去。部分程式碼如下:
int _stdcall GETUSPW()
{
_clsAdoRec * pAccount;
IUnknown *pUnknown;
HRESULT hr;
CoInitialize(NULL);//初始化COM環境
hr = CoInitializeSecurity(
NULL, //Points to security descriptor
-1, //Count of entries in asAuthSvc
NULL, //Array of names to register
NULL, //Reserved for future use
RPC_C_AUTHN_LEVEL_DEFAULT, //The default authentication level for proxies
RPC_C_IMP_LEVEL_IDENTIFY, //The default impersonation level for proxies
NULL, //Reserved; must be set to NULL
0, //Additional client or server-side capabilities
NULL //Reserved for future use
);
COAUTHINFO sAuthInfo;
sAuthInfo.dwAuthnSvc = RPC_C_AUTHN_DEFAULT;
sAuthInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
//sAuthInfo.dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
sAuthInfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;
// sAuthInfo.dwCapabilities = EOAC_NONE;//must be
sAuthInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;//must be
sAuthInfo.pwszServerPrincName = NULL;
sAuthInfo.pAuthIdentityData = (COAUTHIDENTITY*)malloc(sizeof(COAUTHIDENTITY));
sAuthInfo.pAuthIdentityData->User = L"test" ;//訪問遠端物件所在主機的使用者名稱,寬字串
sAuthInfo.pAuthIdentityData->UserLength =4; //使用者名稱的字元長度
sAuthInfo.pAuthIdentityData->Password = L"test" ;//密碼,寬字串
sAuthInfo.pAuthIdentityData->PasswordLength = 4; //密碼長度
sAuthInfo.pAuthIdentityData->Domain = NULL; //遠端主機的域,如果沒有域則設定為NULL
sAuthInfo.pAuthIdentityData->DomainLength = 0;//域名長度
sAuthInfo.pAuthIdentityData->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
COSERVERINFO serverInfo;
memset(&serverInfo, 0, sizeof(COSERVERINFO));
serverInfo.pwszName = L"192.168.1.10"; //遠端主機的名稱
serverInfo.pAuthInfo = &sAuthInfo;
MULTI_QI qi;
memset(&qi, 0, sizeof(MULTI_QI));
qi.pIID = &IID_IUnknown;
CLSID CLSID_InsideCOM = {0xAB363305,0x981B,0x11D1,{0x92,0x92,0x00,0xAA,0x00,0x51,0x0E,0x3B}};
const IID IID_IAccount={0xB363304,0x981B,0x11D1,{0x92,0x92,0x00,0xAA,0x00,0x51,0x0E,0x3B}};
hr=CoCreateInstanceEx(CLSID_InsideCOM,NULL,CLSCTX_REMOTE_SERVER,&serverInfo,1,&qi);
pUnknown = (IUnknown *) qi.pItf;
hr = pUnknown->QueryInterface(IID_IAccount,(void**)&pAccount);
pAccount->GetADORecordset();
pUnknown->Release();
return 0;
}
呼叫該DLL,單步除錯的時候,程式走到CoCreateInstanceEx函式時候沒有問題,接著執行介面查詢操作
QueryInterface,hr返回0x80070005,訪問被拒絕。實在弄不明白,都已經CoCreateInstanceEx成功了,為什麼 QueryInterface不成功呢?是我程式碼寫的有問題嗎?
http://hi.baidu.com/mingyueye/item/53ebecd44da76917d80e4449
相關推薦
[轉]總結一下CSS中的定位 Position 屬性
pub pos solid 修改 static blog style 分享 正常的 在CSS中,Position 屬性經常會用到,主要是絕對定位和相對定位,簡單的使用都沒有問題,尤其嵌套起來,就會有些混亂,今記錄總結一下,防止久而忘之。 CSS positi
如何解決spring中同一個類裡面方法之間呼叫的時候註解失效的問題
參考部落格:https://blog.csdn.net/z55887/article/details/81073450 @RestController public class Test { @Autowired ApplicationContext context;
簡單總結一下Java中的集合
今天面試了深圳遞四方,奇蹟般的過了,在此紀念一下哈哈 技術面有不少問題沒答好,其中一個就是集合,用了這麼久的集合,腦袋裡面還是沒有一個系統的概念,當然要痛定思痛啦! 上一個集合框架圖 然後這個看起來有點混亂,先來一個簡化的 這個圖大概要能回答的出來,常用的還要
java中如何獲得一個方法的呼叫深度?
函式: Thread.currentThread().getStackTrace(); 作用:獲得在同一個執行緒,方法呼叫的深度。 案例: public class DemoTest {
總結一下面試中遇到的問題,一共面試了4家公司。
基本情況:本科畢業一年,面試職位:北京的Android開發職位。 1.搜狗: (1)5種基本的Layout:relative,linear,frame,absolute,table. (2) wait和s
總結一下Android中主題(Theme)的正確玩法
在AndroidManifest.xml檔案中有<application android:theme="@style/AppTheme">,其中的@style/AppTheme是引用的res/values/styles.xml 中的主題樣式,也有可能是引用的 res/values-v11/sty
總結一下linux中的分段機制
這篇文章主要說一下linux對於分段機制的處理,雖然都說linux不使用分段機制,但是分段機制屬於CPU的一個功能,即使linux不使用,也要通過程式碼想辦法繞過它,況且linux也使用到了分段機制中的某些功能。 分段機制主要功能只有兩點: 將實體記憶體劃分為多個段,讓作業系統可以使用
【搬運】總結一下面試中被問到的jdk幾個版本之間的區別問題
1.5 1.自動裝箱與拆箱: 2.列舉(常用來設計單例模式) 3.靜態匯入 4.可變引數 5.內省 1.6 1.Web服務元資料 2.指令碼語言支援 3.JTable的排序和過濾 4.更簡單,更強大的JAX-WS 5.輕量級Http Server 6.嵌入式資料庫 Derby
VC++中擷取字串的方法
在VC++程式設計中,我們有時會遇到關於擷取字串的問題,對於CString型別字串的擷取VC++中有現成的函式可供使用,主要是:CStringMid (int nFirst, int nCount);和BOOL AfxExtractSubString (CString&a
java中子類繼承父類呼叫利用繼承方法時呼叫this
package cn.itcast.test1; class Parent{ public Object getObject(){ return this; } } c
子類繼承父類,重寫父類方法,運用多型時呼叫重寫的方法時呼叫子類的還是呼叫父類的?
package 第五天; public class Person { public void say() { System.out.println("我是Person的say方法"); } } 子類Student如下: package 第五天; publ
總結一下在VC中呼叫COM元件的方法+++VC呼叫遠端COM+元件
總結一下在VC中呼叫COM元件的方法 準備及條件: COM伺服器為程序內伺服器,DLL名為simpCOM.dll,該元件只有一個介面IFoo,該介面只有一個方法HRESULT SayHello(void) 在SDK中呼叫 ====================
vc中呼叫Com元件的方法詳解
需求: 1.建立myCom.dll,該COM只有一個元件,兩個介面: IGetRes--方法Hello(), IGetResEx--方法HelloEx() 2.在工程中匯入元件或型別庫 #import "元件所在目錄myCom.dll" no_namespa
(用iis呼叫com來操縱Excel) 檢索 COM 類工廠中 CLSID 為{00024500-0000-0000-C000-000000000046} 的元件時失敗,原因是出現以下錯誤: 80070005。8000401A的錯誤解決方法
.NET匯出Excel遇到的80070005錯誤的解決方法: 檢索 COM 類工廠中 CLSID 為 {00024500-0000-0000-C000-000000000046}的元件時失敗,原因是出現以下錯誤: 80070005基本上.net匯出excel檔案,都需要如此配置一下,不配置有的時候沒錯,而
VC++中list::list的使用方法總結
本文主題 這幾天在做影象處理方面的研究,其中有一部分是關於影象分割方面的,影象目標在分割出來之後要做進一步的處理,因此有必要將目標影象的資訊儲存在一個變數裡面,一開始想到的是陣列,但是馬上就發現使用陣列的缺點:陣列長度固定
C++呼叫系統中應用程式的方法的整理總結
一、三個SDK函式: WinExec,ShellExecute ,CreateProcess可以實現呼叫其他程式的要求,其中以WinExec最為簡單,ShellExecute比WinExec靈活一些,CreateProcess最為複雜。WinExec 兩個引數,前一個指定路徑,後一個指
C++呼叫com控制元件方法
最近要求做一個C++呼叫com元件的DEMO。由於自己對C++並無研究包括IDE工具。後來在網上查閱了些資料,經過努力終於告一段落。 網上對於C++載入com元件的方法已經說的很多了,我就僅貼下我所使用的方法(不用註冊dll,當然網上推薦了一些更簡單也更有
vue中元件間迴圈呼叫,子元件呼叫最父層方法 的 解決方案
問題描述:最近的VUE專案中遇到樹形結構的選單。複用樹形的選單的元件。但需要呼叫元件最父層的方法。一般父子間元件用 this.$emit 傳遞,或者只有一層的情況下用 this.$parent.xxx可參考:https://cn.vuejs.org/v2/guide/comp
COM元件註冊方法(VC++)
1、開啟VC的屬性介面進行設定 2、註冊DLL到系統 CString szInfo, szPath; char cPath[MAX_PATH] = {0}; GetModuleFileNam
7zip壓縮與解壓縮在vc++中的呼叫方法例子
最近在做關於壓縮與解壓縮的程式,在網上找了很長時間,很多的文章都很難理解,經過大半天的嘗試終於找到一種解決辦法,現在以其中的一種壓縮和解壓縮的方式的例子給大家呈現: 首先要有7zip的可執行檔案7z.exe,假設已經將該可執行檔案放自己的專案目錄下,即和自己的可執行檔案放