|
Hello, developers!
I have a problem, and i don't know how to solve it. Below i describe this situation:
I have a COM object(in C++) without TypeLIB and I there is a late bound client in C#.NET. During work
a COM object send different events to client. And i don't know, how i can recieve this events in C#. If a had a C++ client, i would write this code:
#include "stdafx.h"
#include <basetyps.h>
#include <unknwn.h>
#include <comdef.h>
#include <atlbase.h>
#include <atlcom.h>
#include <ocidl.h>
#include <iostream>
using namespace std;
_COM_SMARTPTR_TYPEDEF(IConnectionPointContainer, __uuidof(IConnectionPointContainer));
_COM_SMARTPTR_TYPEDEF(IConnectionPoint, __uuidof(IConnectionPoint));
_COM_SMARTPTR_TYPEDEF(IEnumConnectionPoints, __uuidof(IEnumConnectionPoints));
class CoFomatikEventSink : IDispatch
{
public:
enum DISPIDS
{
DISPID_OnStateChanged = 1,
DISPID_OnProgressChanged,
};
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
CoFomatikEventSink() : cookie(0), refCount(1) {}
~CoFomatikEventSink() { Disconnect(); }
bool Connect(IUnknownPtr object);
bool Disconnect();
// Event Handlers
void OnStateChanged(IUnknownPtr state);
void OnProgressChanged(UINT value, const BSTR text);
private:
IConnectionPointPtr defaultConnectionPoint;
ULONG cookie;
ULONG refCount;
};
STDMETHODIMP_(ULONG) CoFomatikEventSink::AddRef(void)
{
return ++refCount;
}
STDMETHODIMP_(ULONG) CoFomatikEventSink::Release(void)
{
if(--refCount == 0)
{
delete this;
return 0;
}
return refCount;
}
STDMETHODIMP CoFomatikEventSink::QueryInterface(REFIID riid, void** ppv)
{
if(riid == IID_IUnknown)
*ppv = (IUnknown*)this;
else
if(riid == IID_IDispatch)
*ppv = (IDispatch*)this;
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
((IUnknown*)(*ppv))->AddRef();
return S_OK;
}
STDMETHODIMP CoFomatikEventSink::GetTypeInfoCount(UINT *pctinfo)
{
*pctinfo = 0;
return S_OK;
}
STDMETHODIMP CoFomatikEventSink::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
*ppTInfo = NULL;
return E_NOTIMPL;
}
STDMETHODIMP CoFomatikEventSink::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
for(UINT i = 0; i < cNames; ++i)
{
if(_wcsicmp(rgszNames[i], OLESTR("OnStateChanged")) == 0)
{
rgDispId[i] = DISPID_OnStateChanged;
}
else
if(_wcsicmp(rgszNames[i], OLESTR("OnProgressChanged")) == 0)
{
rgDispId[i] = DISPID_OnProgressChanged;
}
else
return DISP_E_UNKNOWNNAME;
}
return S_OK;
}
STDMETHODIMP CoFomatikEventSink::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
switch(dispIdMember)
{
case DISPID_OnStateChanged:
{
if(pDispParams -> cArgs == 1)
{
OnStateChanged(pDispParams->rgvarg[0].punkVal);
return S_OK;
}
}
break;
case DISPID_OnProgressChanged:
{
if(pDispParams -> cArgs == 2)
{
OnProgressChanged(pDispParams->rgvarg[0].uintVal,pDispParams->rgvarg[1].bstrVal);
return S_OK;
}
}
break;
}
return DISP_E_UNKNOWNINTERFACE;
}
bool CoFomatikEventSink::Connect(IUnknownPtr object)
{
IConnectionPointContainerPtr connectionPointContainer = object;
IEnumConnectionPointsPtr enumConnectionPoints;
ULONG numConnectionPoints = 0;
connectionPointContainer->EnumConnectionPoints(&enumConnectionPoints);
if(enumConnectionPoints->Next(1, &defaultConnectionPoint, &numConnectionPoints ) == S_OK)
{
if(defaultConnectionPoint->Advise(this, &cookie) == S_OK)
{
cout<<cookie<<endl;
return="" true;
="" }
="" defaultconnectionpoint="NULL;
" cookie="0;"
="" false;
}
bool="" cofomatikeventsink::disconnect()
{
="" if(cookie)
="" {
="" defaultconnectionpoint-="">Unadvise(cookie);
defaultConnectionPoint = NULL;
cookie = 0;
}
return true;
}
void CoFomatikEventSink::OnStateChanged(IUnknownPtr state)
{
/* OnStateChanged handler HERE */
}
void CoFomatikEventSink::OnProgressChanged(UINT value, const BSTR text)
{
/* OnProgressChanged handler HERE */
}
// ===========================================================================
int main(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
{
IUnknownPtr fomatik;
fomatik.CreateInstance("MyCOM.Application");
CoFomatikEventSink* ev = new CoFomatikEventSink();
ev->Connect(fomatik);
ev->Release();
}
::CoUninitialize();
}
But i don't know how i can implement IDispatch in C#? Yes, i know, that RCW and CCW do all work to marshal parameters and call functions, and implement IUnknown and IDispatch, but in my application it is neccesary to implement IDispatch myself, because i don't have a TypeLIB for COM object and that's way i can't cache DispIDs from another source.. I have been trying to write this event handler already 3 days, but unsuccessful!!!!
Plese, if anybody know how to solve this problem, help!
Big, hearty thanks in advance!!!!
|
|
|
|
|
I advise you to use 'pre' tags, for readable code. For getting solution.
|
|
|
|
|
Hello all
Could you please help me ?
I have a VC++ application which makes calls to a COM dll which is developed in c# and registered in GAC .
Randomly calls to functions in the dll makes the VC++ application crash with message "run time crash". But there is no __com_error exceptions happening on these calls .
Could any of you help me please to identify what could be the problem?
redindian
|
|
|
|
|
|
Its not sufficient for answer
|
|
|
|
|
hi all
i building a project use Com+
i have 3 Com+
the fist com+ after login i want only Admin can use it(permisstion in Database SQL)
the seacon com+ only Manage can use
the final everyone can use it
Can u hepl me
|
|
|
|
|
With COM+ you can define roles which are containers for users and/or groups.
You can then authorise these roles to use different components.
Steve S
Developer for hire
|
|
|
|
|
I am using VC++ 2005 Pro, created an MFC ActiveX control (From project types MFC, not ATL), then created an MFC dialog application to test the control. In the dialog application, right-clicked on the dialog box and selected 'Insert ActiveX Control', selected my control -- all that is ok. Right-click the control, select "Add Variable" and get the error "The Extender Provider failed to return an Extender for this object"
Any ideas what this means and how to fix it?
|
|
|
|
|
|
Dear all,
I need a DirectShow filter(eitheir source filter or transformer filter or renderer filter ) sample to get the knowledge about directshow filter development.
Manjunath S
GESL
Bangalore
|
|
|
|
|
Hi,
How can I load XML Schema using VC++ 6.0. I'm trying to do this usning MSXML4.0, DOM APIs but I'm not able to read complex XSDs. Would anybody plz help me to do this.
How can I use ISchema, ISchemaElementPtr etc... SOM APIs?
Thanks
Srinivas
|
|
|
|
|
See here[^] maybe its helpful for you
|
|
|
|
|
I have successfully made a DCOM client and server, the client can call functions on the server. My trouble is trying to use MFC to create a connection point so that the server can call a function on the client.
On the client side I created a class ISimpCliAuto derived from COleDispatchDriver that has the exposed functions of the server. This class has a clsid, IID_ISimpCliAuto.
On the server side I have the following macros in the header file of the exposed class, CSimpServDlgAutoProxy:
BEGIN_CONNECTION_PART(CSimpServDlgAutoProxy, Alert)
CONNECTION_IID(IID_ISimpCliAuto)
END_CONNECTION_PART(Alert)
DECLARE_CONNECTION_MAP()
In the SimpServDlgAutoProxy.cpp I have the macros
BEGIN_CONNECTION_MAP(CSimpServDlgAutoProxy, CCmdTarget)
CONNECTION_PART(CSimpServDlgAutoProxy, IID_ISimpCliAuto, Alert)
END_CONNECTION_MAP()
On the client side I call CoCreateInstanceEx() and get an LPUNKNOWN m_pUnkServ. I call m_pUnkServ->QueryInterface() to get an LPDISPATCH which I can use in AttachDispatch(LPDISPATCH) and call exposed functions on the server side. I do not call m_pUnkServ->Release() at this point.
The problem occurs when I attempt to use m_pUnkServ in AfxConnectionAdvise(m_pUnkServ,...). The failure occurs within at the call
LPCONNECTIONPOINTCONTAINER pCPC;
HRESULT hr = m_pUnkServ->QueryInterface(IID_IConnectionPointContainer,(LPVOID*)&pCPC);
The hr indicates "No such interface supported." This is the result locally as well as over a network. The interface in question I think is the connection point container. But isn't all that supported by the macros above in the server? What am I doing wrong?
|
|
|
|
|
Hi,
I am passing a BSTR as an argument in a connectionpoint method. Everything is working fine except that when the BSTR is received by the client, it just gets the first character of the string.
Does anyone know how to solve this?
Thanks...
---
Hakuna-Matada
It means no worries for the rest of your days...
It's our problem free, Philosophy
|
|
|
|
|
Is this a UNICODE or ANSI BSTR ?
Darka [ Xanya]
"I am not a slave to a god that doesn't exist."
|
|
|
|
|
By definition, a true BSTR can only be UNICODE.
Steve S
Developer for hire
|
|
|
|
|
Yes, but you can have ANSI ones too!
regards,
Darka [ Xanya]
"I am not a slave to a god that doesn't exist."
|
|
|
|
|
Not one that's strictly automation compatible; however, there doesn't seem to be anything anywhere in the documentation that says you absolutely can't, since a BSTR is a length-counted block of memory.
Steve S
Developer for hire
|
|
|
|
|
A BSTR which store only ANSI Text. Do you have a solution? If so, could you please share it.
Thanks.
-- modified at 2:03 Friday 13th October, 2006
---
Hakuna-Matada
It means no worries for the rest of your days...
It's our problem free, Philosophy
|
|
|
|
|
Could you post a small code sample ?
Darka [ Xanya]
"I am not a slave to a god that doesn't exist."
|
|
|
|
|
Hello HakunaMatada,
Email me directly :
bio_lim_2004@yahoo.com
I have a COM app sample which receives a BSTR as an event parameter.
- Bio.
|
|
|
|
|
Thanks Bio, but I got the answer. There was a problem with the String conversion from BSTR to CString. A foolish mistake. Once I figured it out, it started working fine.
One question I would like to ask though is, Is there any limit to the number of characters that can be passed via a BSTR in COM? I mean does it make any difference if I passed a string with 1000000 words? Will it be reliable?
Thanks once again.
---
Hakuna-Matada
It means no worries for the rest of your days...
It's our problem free, Philosophy
|
|
|
|
|
Hello HakunaMatada,
Congratulations on discovering the solution to your problem
Concerning the max length of a BSTR : yes there is a limit. Recall that a BSTR is not a NULL-terminated string. The length of the contents of a BSTR is actually stored inside a 4-byte unsigned long value. This 4-byte length indicator is stored in memory immediately before the start of the first byte of the BSTR.
Therefore, the max number of BYTES that can be contained inside a BSTR is 4294967295.
- Bio.
|
|
|
|
|
|
I am trying to recover my permanently deleted outlook mails through coding
I know that der r many software available in the market that can do so
But i want to do it through coding
I know it is done using MAPI's
I am able to import messages when they r present in inbox through code
but facing difficuly in recovering deleted messages
can anybody just help me in this
|
|
|
|
|