|
Yes, you understand it correct. I want to catch events from this server in the .exe file.
At first I worked with an .c / .h / .idl file that have been created from the .exe server. With these I could create an ComPtr and I could call some methods with this pointer. This step works in my old project:
CComPtr<icole2> tCOLE;
hr = CoInitialize(0);
hr = CoCreateInstance(CLSID_COLEv2, 0, CLSCTX_LOCAL_SERVER, IID_ICOLE2, (void**)&tCOLE);
tCole->.... //here I could call the methods out of the ICOLE2.
This worked also perfect.
Now I had the problem that I must catch also some events from the server. And here I didn't know how I should go on. Some people on different forums called me to work with atl because this should be easier. So now I tried to do that all with ATL. The main problem now is, that I didn't exactly know what I must do. I didn't found anywhere an example / tutorial that explains everything step by step.
|
|
|
|
|
 Here's a full example using ATL and #import - the comments should be informative, I hope It references the Excel COM server, obviously running in a separate process. It tells Excel it wants to catch application-specific events (as defined by the interface AppEvents), by telling it what object to send the events to.
#include <iostream>
#include <atlcom.h>
#import "libid:00020813-0000-0000-C000-000000000046" version("1.6") auto_search no_dual_interfaces raw_dispinterfaces rename("DialogBox", "excelDialogBox") rename("RGB", "excelRGB") rename("DocumentProperties", "excelDocumentProperties") rename("SearchPath", "excelSearchPath") rename("CopyFile", "excelCopyFile") rename("ReplaceText", "excelReplaceText")
_ATL_FUNC_INFO SheetChangeInfo = { CC_CDECL, VT_EMPTY, 2, { VT_DISPATCH, VT_DISPATCH } };
class ExcelAppEventHandler : public IDispEventSimpleImpl<1, ExcelAppEventHandler, &__uuidof(Excel::AppEvents)>
{
public:
ExcelAppEventHandler(bool& doneFlag) : done_(doneFlag) { done_ = false; }
BEGIN_SINK_MAP(ExcelAppEventHandler)
SINK_ENTRY_INFO(1, __uuidof(Excel::AppEvents), 0x0000061c, &ExcelAppEventHandler::SheetChange, &SheetChangeInfo)
END_SINK_MAP()
void _stdcall SheetChange(IDispatch * Sh, struct Excel::Range * Target)
{
done_ = true;
}
private:
bool& done_;
};
_bstr_t GetActiveWorkbookName(Excel::_ApplicationPtr xl)
{
if (Excel::_WorkbookPtr wb = xl->ActiveWorkbook)
{
try
{
return wb->FullName;
}
catch(_com_error& e)
{
std::cout << "EXCEPTION!!!\n";
std::cerr << CT2CA(e.ErrorMessage()) << std::endl;
bool done;
ExcelAppEventHandler app(done);
if (SUCCEEDED(app.DispEventAdvise(xl)))
{
MSG msg;
while (!done && GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
app.DispEventUnadvise(xl);
return GetActiveWorkbookName(xl);
}
}
}
return _bstr_t();
}
int _tmain(int argc, _TCHAR* argv[])
{
CoInitializeEx(0, COINIT_APARTMENTTHREADED);
{
Excel::_ApplicationPtr xl;
if (SUCCEEDED(xl.GetActiveObject(__uuidof(Excel::Application))))
{
std::cout << "Getting name\n";
std::cout << GetActiveWorkbookName(xl) << std::endl;
}
}
CoUninitialize();
return 0;
}
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Juergen_80 wrote: Now I need an connection from my .vcproj project to that COM server. Is there anywhere an step by step tutorial with that I can do such something?
I think that "#import directive" is only what you need if you are simply a client of this COM exe server.
Also don't forget about CoInitialize/CoInitializeEx functions before using COM objects and CoUninitialize after.
With best wishes,
Vita
|
|
|
|
|
Hi!
I have an application in MFC unmanaged code compiled with VS2008. My application call a strong-named com-module, registered with RegAsm myCom.dll /tlb:myCom.tlb /codebase, and gacutil /i myCom.dll. myCom-module is coded in c# and compiled with VS2008.
My customer runs my application on a citrix-server through a citrix-client. For most of my customer all works fine but for a few customer the application fails to call my Com-module when they run my application from there workstation, but if they try with the same login from another computer there is no problem at all.
Any clue how to solve my problem?
Best regards,
Bertil
MSc Bertil Morefält
modified on Thursday, September 10, 2009 10:21 AM
|
|
|
|
|
Well.. the scenario is the same com+ behave different on different environment right ?..
RegAsm command register your com into GAC and you also export the tbl. I need to confirm that weather you using the tlb which is exported in a developer / local environment and use this as references for your custom application.
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Hi!
In my developer computer I have registered myCom.dll at .\mycomdir\release and in my code I have #import "c:\mycomdir\release\myCom.tlb" raw_interfaces_only
In the application-server I have registered myCom.dll at the applications home-directory. So, both myCom.dll and myCom.tlb resides in the applications home-directory.
Best regards,
Bertil Morefält
MSc Bertil Morefält
|
|
|
|
|
Okay...Probably you set the COM visible = true from app-> assembly info & Register for COM Interop = true.. in this case you not need to register the COM using RegAsm command in your local machine. I think you can try to add your COM project in your setup and deployment project and set the self register = true... It will might be release your extra pain on thinking of various version of Microsoft Windows OS .
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Hi all,
I have a .NET(C#) DLL which I have to use from Visual Basic 6.0 application. I am using regasm tool to make tlb file and register the dll. Then I can use the tlb file from VB6.
Now I have to make an installer. I have heard that its possible from installer project to make tlb without using regasm tool, but did not get any sample yet.
Is it really possible to register .NET DLL without using regasm? If possible it would be great because I do not need to add any .NET framework in my installer.
If this is possible can anyone please give me a complete sample of this?
Please response.
modified on Saturday, September 12, 2009 4:48 AM
|
|
|
|
|
Yap... It's very easy. you can create an installer of your com+; You just take a setup & deployment project add the primary output files and set the property reg to com true..
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Thank you very much Maruf. That exactly what I wanted.
|
|
|
|
|
You are most welcome.....
I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.
Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.
Thanks
Md. Marufuzzaman
|
|
|
|
|
Hi All,
I’m an absolutely newbie in the COM technology and I have a little tricky question. I hope there’s someone out there who can help me with my problem. I have an .idl / .h / .c file and I integrated them in my VisualStudio 2005 C++ project. After that I’ve searched on the MSDN Library how I can connect an COM Server from my project. I’ve found a little example (http://msdn.microsoft.com/en-us/magazine/cc163361.aspx) and tried to do it on the same way. I’ve created an Csink class and tried to create an instance of this sink object to pass to the server. Now I want to call an function „ OnShowMessageDlg “ out of this Csink class and after that I’ll become the following error message from my compiler:
Linker error: LNK2001: unresolved external symbol public: __thiscall ""public: void __thiscall CSink::OnShowMessageDlg(struct IMsgDlg *,short *)" (?OnShowMessageDlg@CSink@@QAEXPAUIMsgDlg@@PAF@Z)".
Can someone give me a hint what there could be wrong? Or what I must do to use these function? Is the .idl file and the .h file correct? I didn’t find the functions OnShowMessageDlg and OnConfigurationApply in the .h file?
I know, this should be basics I must know. I hope the two books I’ve ordered will arrive as soon as possible.
Please let me know if you need any other information.
Thanks for ANY help.
Juergen
*************************************************************************************************
.idl file
.
.
.
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface ITEST2;
dispinterface ITESTEvents;
.
.
.
[
uuid(6775FB91-B5BE-11D6-A996-0050BA24C7B9),
version(1.1),
helpstring("Event dispatch interface for TEST")
]
dispinterface ITESTEvents {
properties:
methods:
[id(0x00000001)]
void OnConfigurationApply([in, out] VARIANT_BOOL* pAccept);
[id(0x00000002)]
void OnShowMessageDlg(
[in] IMsgDlg* pIMsg,
[out, retval] VARIANT_BOOL* Result);
};
.
.
.
.
coclass TESTv2 {
[default] interface ITEST2;
[default, source] dispinterface ITESTEvents;
};
*************************************************************************************************
.h file
.
.
.
EXTERN_C const IID DIID_ITESTEvents;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("6775FB91-B5BE-11D6-A996-0050BA24C7B9")
ITESTEvents : public IDispatch
{
};
#else /* C style interface */
typedef struct ITESTEventsVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ITESTEvents * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
.
.
.
*************************************************************************************************
.c file
.
.
.
MIDL_DEFINE_GUID(IID, IID_ITEST2,0xF560F761,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(IID, DIID_ITESTEvents,0x6775FB91,0xB5BE,0x11D6,0xA9,0x96,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(CLSID, CLSID_TESTv2,0xF560F763,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
.
.
.
*************************************************************************************************
.c++ file
class CSink : public ITESTEvents
{
public:
CSink::CSink() {m_cRef = 0;}
CSink::~CSink() {}
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID(riid, IID_IUnknown))
*ppvObject = reinterpret_cast<void **> (this);
if (IsEqualGUID(riid, DIID_ITESTEvents))
*ppvObject = reinterpret_cast<void **> (this);
if (*ppvObject)
{
((IUnknown*)*ppvObject)->AddRef();
return S_OK;
}
else return E_NOINTERFACE;
}
DWORD __stdcall AddRef()
{
return InterlockedIncrement(&m_cRef);
}
DWORD __stdcall Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
STDMETHOD(GetTypeInfoCount)(unsigned int FAR* pctinfo)
{ return E_NOTIMPL; }
STDMETHOD(GetTypeInfo)(unsigned int iTInfo, LCID lcid,
ITypeInfo FAR* FAR* ppTInfo)
{ return E_NOTIMPL; }
STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames,
unsigned int cNames, LCID lcid, DISPID FAR* rgDispId)
{ return S_OK; }
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO * pExcepInfo, UINT * puArgErr)
{
return S_OK;
}
public:
void OnConfigurationApply(VARIANT_BOOL *pAccept);
void OnShowMessageDlg(IMsgDlg *pIMsg, VARIANT_BOOL *Result);
private:
DISPID m_id;
long m_cRef;
};
void main(){
.
.
.
CComPtr<ITEST2> tTEST;
HRESULT hr;
hr = CoInitialize(0);
if(FAILED(hr)){
CoUninitialize();
return false;
}
hr = CoCreateInstance(CLSID_TESTv2, 0, CLSCTX_LOCAL_SERVER, IID_ITEST2, (void**)&tTEST);
IConnectionPointContainer * ICPointContainer;
hr = tTEST->QueryInterface(IID_IConnectionPointContainer,(void **)&ICPointContainer);
if(SUCCEEDED(hr)){
//CComPtr<IConnectionPoint> ICPoint;
hr = ICPointContainer->FindConnectionPoint(DIID_ITESTEvents, &ICPoint);
if(SUCCEEDED(hr)){
ICPointContainer->Release();
CSink *pSink;
IUnknown *pSinkUnk;
pSink = new CSink;
hr = pSink->QueryInterface (IID_IUnknown,(void **)&pSinkUnk);
hr = ICPoint->Advise(pSinkUnk,&dwAdvise);
VARIANT_BOOL *tDLGResult;
pSink->AddRef();
pSink->OnShowMessageDlg(tMsgDlg, tDLGResult); // ERROR MESSAGE
.
.
}
*************************************************************************************************
|
|
|
|
|
If you have timelimits in learning and implementing the task, you better should use a high-level COM-Wrapper like MFC oder ATL, then you must not implement the standard-interfaced like IUnknown or IDispatch youself. I think there must be lots of examples on codeproject. The error-message tells you to implement the function OnShowMessageDlg(). This is a function call from the com-server into your com-client, so you need an implementation.
|
|
|
|
|
If you have timelimits in learning and implementing the task..
This is the main problem.
The COM server I must use is an .exe file. Is it the easiest way to create an new ATL project? Is there any Wizard with that I can implement the code from the .exe file / COM server in this new project? Until now I use OleView to create the .idl file from the COM server. Can I then use the files from the ATL project in my C++ project?
|
|
|
|
|
The easiest way to use a COM server that has a type library (which should be most of them) is to use #import[^].
The easiest way to implement a connection point sink (a.k.a. an event sink) is to use ATL and create a class derived from IDispEventSimpleImpl. See this post[^] of mine for an example that handles an event raised by Excel.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Hi All,
I am writing some shell extension that use COM object and faced with the following issue. I need to call some method from COM object but I get this error: "hResult 0x80070542 Either a required impersonation level was not provided, or the provided impersonation level is invalid. HRESULT" The same code works fine in console app, because I manually CoInitializeSecurity before call the method, but in shell extension I cannot call CoInitializeSecurity by myself becase I get error that it was already called. How can I setup neccessery permision for this COM object?
Thanks.
|
|
|
|
|
Hi All,
I’m an absolutely newbie in the COM technology and I have a little tricky question. I hope there’s someone out there who can help me with my problem. I have an .idl / .h / .c file and I integrated them in my VisualStudio 2005 C++ project. After that I’ve searched on the MSDN Library how I can connect an COM Server from my project. I’ve found a little example (http://msdn.microsoft.com/en-us/magazine/cc163361.aspx) and tried to do it on the same way. I’ve created an Csink class and tried to create an instance of this sink object to pass to the server. But the problem now I get from my compiler is the following error message: „error C2259: 'CSink': cannot instantiate abstract class due to following members: 'HRESULT IUnknown::QueryInterface(const IID &,void **)' : is abstract“. The thing I need is that I must call the „ OnShowMessageDlg “ and the „ OnConfigurationApply “ functions out of the .idl file in my main c++ function. I’ve put all the code here below this entry that could help you to become an overview about my problem. Is the solution I’ve tried with the sink object correct or should I use another way to do this?
Please let me know if you need any other information.
Thanks for ANY help.
*************************************************************************************************
.idl file
.
.
.
// TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// Forward declare all types defined in this typelib
interface ITEST2;
dispinterface ITESTEvents;
.
.
.
[
uuid(6775FB91-B5BE-11D6-A996-0050BA24C7B9),
version(1.1),
helpstring("Event dispatch interface for TEST")
]
dispinterface ITESTEvents {
properties:
methods:
[id(0x00000001)]
void OnConfigurationApply([in, out] VARIANT_BOOL* pAccept);
[id(0x00000002)]
void OnShowMessageDlg(
[in] IMsgDlg* pIMsg,
[out, retval] VARIANT_BOOL* Result);
};
.
.
.
.
coclass TESTv2 {
[default] interface ITEST2;
[default, source] dispinterface ITESTEvents;
};
*************************************************************************************************
.h file
.
.
.
EXTERN_C const IID DIID_ITESTEvents;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("6775FB91-B5BE-11D6-A996-0050BA24C7B9")
ITESTEvents : public IDispatch
{
};
#else /* C style interface */
typedef struct ITESTEventsVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ITESTEvents * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
.
.
.
*************************************************************************************************
.c file
.
.
.
MIDL_DEFINE_GUID(IID, IID_ITEST2,0xF560F761,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(IID, DIID_ITESTEvents,0x6775FB91,0xB5BE,0x11D6,0xA9,0x96,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(CLSID, CLSID_TESTv2,0xF560F763,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
.
.
.
*************************************************************************************************
.c++ file
class CSink : public ITESTEvents
{
private:
DWORD m_dwRefCount;
public:
CSink::CSink() {m_dwRefCount = 0;}
CSink::~CSink() {}
void OnConfigurationApply(VARIANT_BOOL* pAccept);
void OnShowMessageDlg(IMsgDlg* pIMsg, VARIANT_BOOL* Result);
};
void main(){
.
.
.
CSink *pSink;
pSink = new CSink(); // ERROR MESSAGE
.
.
}
*************************************************************************************************
|
|
|
|
|
You need to implement the methods of the interfaces that ITESTEvents inherits from - that's going to be IDispatch, which in turn inherits from IUnknown. That's a fair bit of work...
There are a couple of CodeProject articles that might be of use: here[^] and here[^].
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thanks for your reply. I think, now the next step can be done.
|
|
|
|
|
Hello friend !!
I want to do show/hide of custom toolbar. I can do it in Windows XP by updating registry, but how can do this in windows 2000 with IE6.There are no menu for manage for add ons in IE6 with Win2000. So what is alternative way to manage add ons in windows 2000?
Thanks
ABM
|
|
|
|
|
When I loged in a site and clicked the url link in a webbrowser,
system launched a new IE windows but let me login again,
the cookies in the new windows has been lost.
How to pass session in a new IE process?
thanks.
There is some code below.
void CWebSee::OnNewWindow2Explorer1(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel)
{
TRACE("NewWindow");
*Cancel = FALSE;
IWebBrowser2* m_pWebBrowser2=NULL;
HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL,
CLSCTX_LOCAL_SERVER, IID_IWebBrowser2,
(void**)&m_pWebBrowser2);
if (hr == S_OK)
*ppDisp = (IDispatch*)m_pWebBrowser2;
hr = m_pWebBrowser2->put_StatusBar(VARIANT_FALSE);
hr = m_pWebBrowser2->put_ToolBar(VARIANT_TRUE);
hr = m_pWebBrowser2->put_MenuBar(VARIANT_FALSE);
hr = m_pWebBrowser2->put_Visible(VARIANT_TRUE);
...
|
|
|
|
|
Hi
I want to hide my custom toolbar on IE(all versions). I can hide standard IE toolbar by using
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Internet Explorer\Toolbars\Restrictions
NoToolBar" Value = 1
which hides all standard button from IE. But i want to hide my Toolbar whenever browser starts and show it at particular site. So is there any way to hide by regedit by knowing the guid of toolbar.
Thanks
abc
|
|
|
|
|
Hello ,
I want to use #import "c:\program files\common files\myfile.dll for Windows XP and
#import "c:\WINNT\common files\myfile.dll for windows 2000.
if I use two statement at a time , compiler gives me error as "no such file". So how can I use both statement at a time.
Thanks
ABC
|
|
|
|
|
The location you use for #import depends on the OS you're building the project on - do you anticipate building the project on both Windows 2000 AND XP?
Alternatively, use the #import "libid:library UUID" syntax.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Yes , I want to build project on both Windows 2000 and Windows XP.
Thanks
abc
|
|
|
|
|