VC调用VB的COM+组件
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不成功呢?是我代码写的有问题吗?大家帮我看看,谢谢