ATL Service - Need to establish sink for a connection point of ActiveX dll
Author |
Message |
Ofir #1 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi, I have an ActiveX dll with a connection point, and i need to use it in the ATL service. I tried to create and MFC based class ( class CNotify : public CCmdTarget ) with the appropriate definitions for the sink event: BEGIN_DISPATCH_MAP( CNotify, CCmdTarget) DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY, VTS_R8) END_DISPATCH_MAP( ) BEGIN_INTERFACE_MAP( CNotify, CCmdTarget) INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch) END_INTERFACE_MAP() (this class is in test use in MFC application and the sink event is working) at the constructor of this class i execute the AfxConnectionAdvise method: BOOL Ret = ::AfxConnectionAdvise( m_pRepTimer, DIID___ciTimer, GetIDispatch(FALSE), //get the IDispatch assocaiated with CServiceManagerDlg... FALSE, //donod addref &dwCookie );//cookie to break connection later... so in MFC application the sink is working and in ATL service it failed and i don't know why. I tried another test, the same class using ATL instead of MFC : class CNotifyEvents : public IDispatchImpl<__ciTimer, &DIID___ciTimer, &CLSID_ciTimer>, public CComObjectRoot and instead of AfxConnectionAdvise i used : HRESULT hr=AtlAdvise(m_pRepTimer, GetUnknown(), DIID___ciTimer, &dwCookie); I think that my Major problem is at the second parameter GetUnknown() ( or in the first case, the third parameter : GetIDispatch(FALSE) ) that failes in ATL service, can somebody help me to know how can i establish sink event in NON-WINDOWS environment ? Is there any special solution for ATL service? Thank you, Ofir
|
Fri, 27 Aug 2004 17:45:17 GMT |
|
 |
Sven Carstense #2 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi, see inline:
Quote: > Hi, > I have an ActiveX dll with a connection point, and i need to use it in the > ATL service. > I tried to create and mfc based class ( class CNotify : public CCmdTarget ) > with the appropriate definitions for the sink event: > BEGIN_DISPATCH_MAP( CNotify, CCmdTarget) > DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY, > VTS_R8) > END_DISPATCH_MAP( ) > BEGIN_INTERFACE_MAP( CNotify, CCmdTarget) > INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch) > END_INTERFACE_MAP() > (this class is in test use in MFC application and the sink event is working) > at the constructor of this class i execute the AfxConnectionAdvise method: > BOOL Ret = ::AfxConnectionAdvise( > m_pRepTimer, > DIID___ciTimer, > GetIDispatch(FALSE), //get the IDispatch assocaiated with > CServiceManagerDlg... > FALSE, //donod addref > &dwCookie );//cookie to break connection later... > so in MFC application the sink is working and in ATL service it failed and i > don't know why. > I tried another test, the same class using ATL instead of MFC : > class CNotifyEvents : > public IDispatchImpl<__ciTimer, &DIID___ciTimer, > &CLSID_ciTimer>, > public CComObjectRoot > and instead of AfxConnectionAdvise i used : > HRESULT hr=AtlAdvise(m_pRepTimer, > GetUnknown(), > DIID___ciTimer, > &dwCookie);
You call AtlAdvise from within a CNotifyEvents instance method? Otherwise there will be no GetUnknown() method to call. What is the hr value. Quote: > I think that my Major problem is at the second parameter GetUnknown() ( or > in the first case, the third parameter : GetIDispatch(FALSE) ) that failes > in ATL service, can somebody help me to know how can i establish sink event > in NON-WINDOWS environment ? > Is there any special solution for ATL service?
What do you mean by establish a sink event in a NON-WINDOWS environment??? Bye, Sven
|
Fri, 27 Aug 2004 21:57:19 GMT |
|
 |
Sven Carstense #3 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi,
Quote: > Hi Sven, > You call AtlAdvise from within a CNotifyEvents instance method? > --yes, i am doing so, why? it did work at the first test when i used > AfxConnectionAdvise. > --is there difference in the location of AfxConnectionAdvise and AtlAdvise > ?
Just wanted to make sure that ATL's GetUnknown() is called and returns the valid IUnknown*. Quote: > What is the hr value? > -- in the service i don't know, because i don't know how to debug it on the > first time, before it creates the process, and it create a process for it > -- just after the the execution of the Start of the service > -- i know that the problem is there because when i remove the AtlAdvise it > does not fail. > -- the AtlAdvice failed also in the MFC application test, and i have no idea > why > -- I get the message box : "Runtime error - R6025 - pure virtual function > call" , with Abord/Retry/Ignore buttons, and when i press Retry i get to > \VC98\CRT\SRC\CRTOMSG.C to the lines : > if (rterrnum != _RT_CRNL) > { > if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL, > rterrs[tblindx].rterrtxt)) > _CrtDbgBreak(); > } > So i don't know why it failes.
Have a look at the call stack to see from where the _CrtDbgReport is called. Quote: > I did not find any example of service with sink event on the MSDN and i > don't understand what is the problem > I am attaching a zip file of the two classes of the tests (CNotify, > CNotifyEvent) in case that it is interesting you. > the CNotify class is working on MFC Application but does not work on ATL > service > the CNotifyEvent class does not working on both. > > What do you mean by establish a sink event in a NON-WINDOWS environment??? > I am not sure, but as much as i understood the Advise functions expect to > get an IUnknown pointer to a window interface that suppose to be able to > handle/accept messages, and in the case of the AtlService i don't think > that i have one. > so can you please tell me which IUnknown suppose to be the client's IUnknown > (in my case my class CNotifyEvents suppose to handle the sink) in case of > ATL service ? > Do you have any basice example of the usage of Sink in the ATL service ? I > will be thankful for that.
COM events have nothing to do (well except if marshaling comes in the way but that's kind of transparent if you behave well ;-) ) windows. GetUnknown() should return the IUnknown implementation fo ATL for your object. There is an ambiguity when casting your C++ class to IUnknown when you implement more than one interface so GetUnknown helps in returning the correct IUnknown*. How do you create a CNotifyEvents instance - can I see some code? Bye, Sven Quote: > Thank you for the help Sven, > Ofir
> > Hi, > > see inline:
> > > Hi, > > > I have an ActiveX dll with a connection point, and i need to use it in > the > > > ATL service. > > > I tried to create and mfc based class ( class CNotify : public > > CCmdTarget ) > > > with the appropriate definitions for the sink event: > > > BEGIN_DISPATCH_MAP( CNotify, CCmdTarget) > > > DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY, > > > VTS_R8) > > > END_DISPATCH_MAP( ) > > > BEGIN_INTERFACE_MAP( CNotify, CCmdTarget) > > > INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch) > > > END_INTERFACE_MAP() > > > (this class is in test use in MFC application and the sink event is > > working) > > > at the constructor of this class i execute the AfxConnectionAdvise > method: > > > BOOL Ret = ::AfxConnectionAdvise( > > > m_pRepTimer, > > > DIID___ciTimer, > > > GetIDispatch(FALSE), //get the IDispatch assocaiated with > > > CServiceManagerDlg... > > > FALSE, //donod addref > > > &dwCookie );//cookie to break connection later... > > > so in MFC application the sink is working and in ATL service it failed > and > > i > > > don't know why. > > > I tried another test, the same class using ATL instead of MFC : > > > class CNotifyEvents : > > > public IDispatchImpl<__ciTimer, &DIID___ciTimer, > > > &CLSID_ciTimer>, > > > public CComObjectRoot > > > and instead of AfxConnectionAdvise i used : > > > HRESULT hr=AtlAdvise(m_pRepTimer, > > > GetUnknown(), > > > DIID___ciTimer, > > > &dwCookie); > > You call AtlAdvise from within a CNotifyEvents instance method? Otherwise > > there will be no GetUnknown() method to call. > > What is the hr value. > > > I think that my Major problem is at the second parameter GetUnknown() > ( or > > > in the first case, the third parameter : GetIDispatch(FALSE) ) that > > failes > > > in ATL service, can somebody help me to know how can i establish sink > > event > > > in NON-WINDOWS environment ? > > > Is there any special solution for ATL service? > > What do you mean by establish a sink event in a NON-WINDOWS environment??? > > Bye, > > Sven
|
Sat, 28 Aug 2004 00:34:41 GMT |
|
 |
Sven Carstense #4 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi, I had a look at your attachments. You are calling AtlAdvise from within your constructor: m_pReqTimer is still NULL at that time. InitiateReplication is a far better place. What's your problem with calling AtlAdvise at that point? GetIDispatch is a helper function from MFC's CCmdTarget to get the corresponding IDispatch interface from an CCmdTarget derived class - it's just not available if don't use MFC to implement your COM object. In ATL you should use GetUnknown(). What's still missing is how do you create an instance of CNotifyEvents? It should be: CComObject<CNotifyEvents> *p = NULL; HRESULT hr = p->CreateInstance(&p); if(FAILED(hr)) { // ouch delete p; Quote: }
else { p->InitiateReplication(); Quote: }
Bye, Sven
Quote: > Hi Sven, > You call AtlAdvise from within a CNotifyEvents instance method? > --yes, i am doing so, why? it did work at the first test when i used > AfxConnectionAdvise. > --is there difference in the location of AfxConnectionAdvise and AtlAdvise > ? > What is the hr value? > -- in the service i don't know, because i don't know how to debug it on the > first time, before it creates the process, and it create a process for it > -- just after the the execution of the Start of the service > -- i know that the problem is there because when i remove the AtlAdvise it > does not fail. > -- the AtlAdvice failed also in the MFC application test, and i have no idea > why > -- I get the message box : "Runtime error - R6025 - pure virtual function > call" , with Abord/Retry/Ignore buttons, and when i press Retry i get to > \VC98\CRT\SRC\CRTOMSG.C to the lines : > if (rterrnum != _RT_CRNL) > { > if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL, > rterrs[tblindx].rterrtxt)) > _CrtDbgBreak(); > } > So i don't know why it failes. > I did not find any example of service with sink event on the MSDN and i > don't understand what is the problem > I am attaching a zip file of the two classes of the tests (CNotify, > CNotifyEvent) in case that it is interesting you. > the CNotify class is working on MFC Application but does not work on ATL > service > the CNotifyEvent class does not working on both. > > What do you mean by establish a sink event in a NON-WINDOWS environment??? > I am not sure, but as much as i understood the Advise functions expect to > get an IUnknown pointer to a window interface that suppose to be able to > handle/accept messages, and in the case of the AtlService i don't think > that i have one. > so can you please tell me which IUnknown suppose to be the client's IUnknown > (in my case my class CNotifyEvents suppose to handle the sink) in case of > ATL service ? > Do you have any basice example of the usage of Sink in the ATL service ? I > will be thankful for that. > Thank you for the help Sven, > Ofir
> > Hi, > > see inline:
> > > Hi, > > > I have an ActiveX dll with a connection point, and i need to use it in > the > > > ATL service. > > > I tried to create and mfc based class ( class CNotify : public > > CCmdTarget ) > > > with the appropriate definitions for the sink event: > > > BEGIN_DISPATCH_MAP( CNotify, CCmdTarget) > > > DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY, > > > VTS_R8) > > > END_DISPATCH_MAP( ) > > > BEGIN_INTERFACE_MAP( CNotify, CCmdTarget) > > > INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch) > > > END_INTERFACE_MAP() > > > (this class is in test use in MFC application and the sink event is > > working) > > > at the constructor of this class i execute the AfxConnectionAdvise > method: > > > BOOL Ret = ::AfxConnectionAdvise( > > > m_pRepTimer, > > > DIID___ciTimer, > > > GetIDispatch(FALSE), //get the IDispatch assocaiated with > > > CServiceManagerDlg... > > > FALSE, //donod addref > > > &dwCookie );//cookie to break connection later... > > > so in MFC application the sink is working and in ATL service it failed > and > > i > > > don't know why. > > > I tried another test, the same class using ATL instead of MFC : > > > class CNotifyEvents : > > > public IDispatchImpl<__ciTimer, &DIID___ciTimer, > > > &CLSID_ciTimer>, > > > public CComObjectRoot > > > and instead of AfxConnectionAdvise i used : > > > HRESULT hr=AtlAdvise(m_pRepTimer, > > > GetUnknown(), > > > DIID___ciTimer, > > > &dwCookie); > > You call AtlAdvise from within a CNotifyEvents instance method? Otherwise > > there will be no GetUnknown() method to call. > > What is the hr value. > > > I think that my Major problem is at the second parameter GetUnknown() > ( or > > > in the first case, the third parameter : GetIDispatch(FALSE) ) that > > failes > > > in ATL service, can somebody help me to know how can i establish sink > > event > > > in NON-WINDOWS environment ? > > > Is there any special solution for ATL service? > > What do you mean by establish a sink event in a NON-WINDOWS environment??? > > Bye, > > Sven
|
Sat, 28 Aug 2004 01:08:39 GMT |
|
 |
Sven Carstense #5 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi Ofir, too fast - I thought you were just asking me by mail so I wrote back by mail without keeping a copy of the reply. To keep all the content in this thread, maybe you could just insert my mail content here. Thanx, Sven
Hi Sven, I want to thank you very much for all your help, i completed the first step and the atl class for the sink event is working (a little different way that i found on the MSDN - you can see it on the attachements) on the test, and i learned a lot about my mistakes from your explanations. So now i have got the class for the sink event and the way to work with it, but on the test. I have read a lot of information about the ATL service (it's my first time with services) on the MSDN, but i have got two types of problems with it: 1. i don't know how to debug it at the first time that i am starting the service, because just after the first time it's running (and get stuck...) i am able to select "DEBUG" from the drop down of the Task Manager Processes list of windows and to set breakpoints in the events. but because it's already ran the major functions that i plan to debug, it's not useful. 2. I am not sure that i know where to put the appropriate methods in the CServiceModule class that the wizard produce for me, but anyway, what i tried did not work: (***) i was able to define it only as global : CComObject<CNotifyEvents> *NotifyEventObj; because this include : #include <atlcom.h> ( for the usage of CComObject in the definition CComObject<CNotifyEvents> *NotifyEventObj; requires the definition of _Module : CServiceModule _Module; I did not find other solution how to define it - CComObject<CNotifyEvents> *NotifyEventObj; - as member of my CNotifyEvents class (***) i wrote this code at the end of the ServiceMain function, it suppose to create an instance (if it has not been created yet) and to execute the InitiateReplication function that suppose to do some database connection job and to execute the AtlAdvise if (NotifyEventObj==NULL) { hr=NotifyEventObj->CreateInstance(&NotifyEventObj); if (FAILED(hr)) { delete NotifyEventObj; } else { NotifyEventObj->InitiateReplication(); } } StartSync(); (***) I wrote this code inline the Handler function. i need it to do the following in case that the user stop the service or start it : inline void CServiceModule::Handler(DWORD dwOpcode) { switch (dwOpcode) { case SERVICE_CONTROL_STOP: SetServiceStatus(SERVICE_STOP_PENDING); PostThreadMessage(dwThreadID, WM_QUIT, 0, 0); StartSync(); //DistroyReplication(); break; case SERVICE_CONTROL_PAUSE: //StopSync(); break; case SERVICE_CONTROL_CONTINUE: StartSync(); break; case SERVICE_CONTROL_INTERROGATE: break; case SERVICE_CONTROL_SHUTDOWN: StopSync(); break; default: LogEvent(_T("Bad service request")); } } when this two functions content is : void CServiceModule::StartSync() { NotifyEventObj->StartTimer(); } void CServiceModule::StopSync() { NotifyEventObj->StopTimer(); } Thank you for any help, Ofir
> Hi, > > I had a look at your attachments. > > You are calling AtlAdvise from within your constructor: m_pReqTimer is still > NULL at that time. > InitiateReplication is a far better place. What's your problem with calling > AtlAdvise at that point? > > GetIDispatch is a helper function from MFC's CCmdTarget to get the > corresponding IDispatch interface from an CCmdTarget derived class - it's > just not available if don't use MFC to implement your COM object. In ATL you > should use GetUnknown(). > > What's still missing is how do you create an instance of CNotifyEvents? It > should be: > > CComObject<CNotifyEvents> *p = NULL; > HRESULT hr = p->CreateInstance(&p); > if(FAILED(hr)) > { > // ouch > delete p; > } > else > { > p->InitiateReplication(); > } > > Bye, > Sven >
> > Hi Sven, > > > > You call AtlAdvise from within a CNotifyEvents instance method? > > > > --yes, i am doing so, why? it did work at the first test when i used > > AfxConnectionAdvise. > > --is there difference in the location of AfxConnectionAdvise and > AtlAdvise > > ? > > > > What is the hr value? > > > > -- in the service i don't know, because i don't know how to debug it on > the > > first time, before it creates the process, and it create a process for it > > -- just after the the execution of the Start of the service > > -- i know that the problem is there because when i remove the AtlAdvise it > > does not fail. > > > > -- the AtlAdvice failed also in the MFC application test, and i have no > idea > > why > > -- I get the message box : "Runtime error - R6025 - pure virtual function > > call" , with Abord/Retry/Ignore buttons, and when i press Retry i get to > > \VC98\CRT\SRC\CRTOMSG.C to the lines : > > > > if (rterrnum != _RT_CRNL) > > { > > if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL, > > rterrs[tblindx].rterrtxt)) > > _CrtDbgBreak(); > > } > > > > So i don't know why it failes. > > > > I did not find any example of service with sink event on the MSDN and i > > don't understand what is the problem > > I am attaching a zip file of the two classes of the tests (CNotify, > > CNotifyEvent) in case that it is interesting you. > > the CNotify class is working on MFC Application but does not work on ATL > > service > > the CNotifyEvent class does not working on both. > > > > > > > What do you mean by establish a sink event in a NON-WINDOWS > environment??? > > > > I am not sure, but as much as i understood the Advise functions expect to > > get an IUnknown pointer to a window interface that suppose to be able to > > handle/accept messages, and in the case of the AtlService i don't think > > that i have one. > > so can you please tell me which IUnknown suppose to be the client's > IUnknown > > (in my case my class CNotifyEvents suppose to handle the sink) in case of > > ATL service ? > > Do you have any basice example of the usage of Sink in the ATL service ? I > > will be thankful for that. > > > > > > Thank you for the help Sven, > > > > Ofir
> > > >
> > > Hi, > > > > > > see inline: > > >
> > > > Hi, > > > > > > > > I have an ActiveX dll with a connection point, and i need to use it in > > the > > > > ATL service. > > > > I tried to create and mfc based class ( class CNotify : public > > > CCmdTarget ) > > > > with the appropriate definitions for the sink event: > > > > > > > > BEGIN_DISPATCH_MAP( CNotify, CCmdTarget) > > > > DISP_FUNCTION_ID(CNotify, "ClassesProgress", 0x1, OnNotify, VT_EMPTY, > > > > VTS_R8) > > > > END_DISPATCH_MAP( ) > > > > > > > > BEGIN_INTERFACE_MAP( CNotify, CCmdTarget) > > > > INTERFACE_PART(CNotify, DIID___ciTimer, Dispatch) > > > > END_INTERFACE_MAP() > > > > > > > > (this class is in test use in MFC application and the sink event is > > > working) > > > > > > > > at the constructor of this class i execute the AfxConnectionAdvise > > method: > > > > > > > > BOOL Ret = ::AfxConnectionAdvise( > > > > m_pRepTimer, > > > > DIID___ciTimer, > > > > GetIDispatch(FALSE), //get the IDispatch assocaiated with > > > > CServiceManagerDlg... > > > > FALSE, //donod addref > > > > &dwCookie );//cookie to break connection later... > > > > > > > > > > > > so in MFC application the sink is working and in ATL service it failed > > and > > > i > > > > don't know why. > > > > > > > > I tried another test, the same class using ATL instead of MFC : > > > > class CNotifyEvents : > > > > public IDispatchImpl<__ciTimer, &DIID___ciTimer, > > > > &CLSID_ciTimer>, > > > > public CComObjectRoot > > > > > > > > and instead of AfxConnectionAdvise i used : > > > > > > > > HRESULT hr=AtlAdvise(m_pRepTimer, > > > > GetUnknown(), > > > > DIID___ciTimer, > > > > &dwCookie); > > > > > > You call AtlAdvise from within a CNotifyEvents instance method? > Otherwise > > > there will be no GetUnknown() method to call. > > > What is the hr value. > > > > > > > I think that my Major problem is at the second parameter GetUnknown() > > ( or > > > > in the first case, the third parameter : GetIDispatch(FALSE) ) that > > > failes > > > > in ATL service, can somebody help me to know how can i establish sink > > > event > > > > in NON-WINDOWS environment ? > > > > Is there any special solution for ATL service? > > > > > > What do you mean by establish a sink event in a NON-WINDOWS > environment??? > > > > > > Bye, > > > Sven > > > > > > > > > > > > > > > > >
|
Sun, 29 Aug 2004 01:09:48 GMT |
|
 |
Ofir #6 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi Svan, Thank you again for your great help and tips. (This mail is already on the news groups vc.atl) Finally i am able to debug the service and i must say that it's thanks to you. As you asked me to, i put the line : MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY); in the _tWinMain just before the line : _Module.Start(); I see that i failed in the Run() function on the method CoInitializeSecurity. the HRESULT that i get there is : -2147417831 (80010119) Security must be initialized before any interfaces are marshalled or unmarshalled. It cannot be changed once initialized. There is information about it on the MSDN : INFO: Translating Automation Errors for VB/VBA (Long) , ID: Q186063 So i commented this lines out and now the "start service" actually working: /* CSecurityDescriptor sd; sd.InitializeFromThreadToken(); hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); _ASSERTE(SUCCEEDED(hr)); */ There is solution for it without excluding this code? how important is this security issue? Now when i stop the service and i debug it, i see that when i stop the sevice, it's try to execute the StopTimer() method of the component (that actually tells it to stop raising the Notify event in the CNotifyEvents class of the service) it probably fialed and distroy the NotifyEventObj object. I tried to catch the error, but i don't know why it ignore any TRY-CATCH that i put, anyway i don't get any failure message at this point. I also though that the reason for this failure is the CoInitialize and CoUninitialize in the CServiceModule::Run(), but after i removed it nothing changed, the problem is still there. I also tried to understand the smart pointer idea, but i did not really understand it. in my case, the class CNotifyEvents had no interface id - INotifyEvents (as much as i know), and i don't suppose to expose one because this class suppose to be completely internal for catching the sink event and handling it. please correct me if i misunderstand you. Best regards, Ofir Hi Ofir, 1) to Debug a service from the start I like the following contruct: inside WinMain or ServiceMain: ... // some code MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY); ... // the code I wan't to debug When the service starts it will display the messagebox (MB_DEFAULT_DESKTOP_ONLY does the trick!). Now you can attach the de{*filter*} to the service. Put a breakpoint right after the MessageBox call and start debugging. 2) You could store a smart pointer to IUnknown or another interface exposed by CNotifyEvents in your CServiceModule: CComPtr<INotifyEvents> m_spNotifyEvents. In Run() or Start() of your CServiceModule you can then use CComObject<CNotifyEvents> *p just locally to create the instance and store an interface pointer in your smart pointer member with a call to p->QueryInterface(&m_spNotifyEvents). This would also handle ref counting automatically. I hope I got alll your questions. Bye, Sven
Hi Ofir, too fast - I thought you were just asking me by mail so I wrote back by mail without keeping a copy of the reply. To keep all the content in this thread, maybe you could just insert my mail content here. Thanx, Sven
Hi Sven, I want to thank you very much for all your help, i completed the first step and the atl class for the sink event is working (a little different way that i found on the MSDN - you can see it on the attachements) on the test, and i learned a lot about my mistakes from your explanations. So now i have got the class for the sink event and the way to work with it, but on the test. I have read a lot of information about the ATL service (it's my first time with services) on the MSDN, but i have got two types of problems with it: 1. i don't know how to debug it at the first time that i am starting the service, because just after the first time it's running (and get stuck...) i am able to select "DEBUG" from the drop down of the Task Manager Processes list of windows and to set breakpoints in the events. but because it's already ran the major functions that i plan to debug, it's not useful. 2. I am not sure that i know where to put the appropriate methods in the CServiceModule class that the wizard produce for me, but anyway, what i tried did not work: (***) i was able to define it only as global : CComObject<CNotifyEvents> *NotifyEventObj; because this include : #include <atlcom.h> ( for the usage of CComObject in the definition CComObject<CNotifyEvents> *NotifyEventObj; requires the definition of _Module : CServiceModule _Module; I did not find other solution how to define it - CComObject<CNotifyEvents> *NotifyEventObj; - as member of my CNotifyEvents class (***) i wrote this code at the end of the ServiceMain function, it suppose to create an instance (if it has not been created yet) and to execute the InitiateReplication function that suppose to do some database connection job and to execute the AtlAdvise if (NotifyEventObj==NULL) { hr=NotifyEventObj->CreateInstance(&NotifyEventObj); if (FAILED(hr)) { delete NotifyEventObj; } else { NotifyEventObj->InitiateReplication(); } } StartSync(); (***) I wrote this code inline the Handler function. i need it to do the following in case that the user stop the service or start it : inline void CServiceModule::Handler(DWORD dwOpcode) { switch (dwOpcode) { case SERVICE_CONTROL_STOP: SetServiceStatus(SERVICE_STOP_PENDING); PostThreadMessage(dwThreadID, WM_QUIT, 0, 0); StartSync(); //DistroyReplication(); break; case SERVICE_CONTROL_PAUSE: //StopSync(); break; case SERVICE_CONTROL_CONTINUE: StartSync(); break; case SERVICE_CONTROL_INTERROGATE: break; case SERVICE_CONTROL_SHUTDOWN: StopSync(); break; default: LogEvent(_T("Bad service request")); } } when this two functions content is : void CServiceModule::StartSync() { NotifyEventObj->StartTimer(); } void CServiceModule::StopSync() { NotifyEventObj->StopTimer(); } Thank you for any help, Ofir
> Hi, > > I had a look at your attachments. > > You are calling AtlAdvise from within your constructor: m_pReqTimer is still > NULL at that time. > InitiateReplication is a far better place. What's your problem with calling > AtlAdvise at that point? > > GetIDispatch is a helper function from MFC's CCmdTarget to get the > corresponding IDispatch interface from an CCmdTarget derived class - it's > just not available if don't use MFC to implement your COM object. In ATL you > should use GetUnknown(). > > What's still missing is how do you create an instance of CNotifyEvents? It > should be: > > CComObject<CNotifyEvents> *p = NULL; > HRESULT hr = p->CreateInstance(&p); > if(FAILED(hr)) > { > // ouch > delete p; > } > else > { > p->InitiateReplication(); > } > > Bye, > Sven >
> > Hi Sven, > > > > You call AtlAdvise from within a CNotifyEvents instance method? > > > > --yes, i am doing so, why? it did work at the first test when i used > > AfxConnectionAdvise. > > --is there difference in the location of AfxConnectionAdvise and > AtlAdvise > > ? > > > > What is the hr value? > > > > -- in the service i don't know, because i don't know how to debug it on > the > > first time, before it creates the process, and it create a process for it > > -- just after the the execution of the Start of the service > > -- i know that the problem is there because when i remove the AtlAdvise it > > does not fail. > > > > -- the AtlAdvice failed also in the MFC application test, and i have no > idea > > why > > -- I get the message box : "Runtime error - R6025 - pure virtual function > > call" , with Abord/Retry/Ignore buttons, and when i press Retry i get to > > \VC98\CRT\SRC\CRTOMSG.C to the lines : > > > > if (rterrnum != _RT_CRNL) > > { > > if (1 == _CrtDbgReport(_CRT_ERROR, NULL, 0, NULL, > > rterrs[tblindx].rterrtxt)) > > _CrtDbgBreak(); > > } > > > > So i don't know why it failes. > > > > I did not find any example of service with sink event on the MSDN and i > > don't understand what is the problem > > I am attaching a zip file of the two classes of the tests (CNotify, > > CNotifyEvent) in case that it is interesting you. > > the CNotify class is working on MFC Application but does not work on ATL > > service > > the CNotifyEvent class does not working on both. > > > > > > > What do you mean by establish a sink event in a NON-WINDOWS > environment??? > > > > I am not sure, but as much as i understood the Advise functions expect to > > get an IUnknown pointer to a window interface that suppose to be able to > > handle/accept messages, and in the case of the
... read more »
|
Sun, 29 Aug 2004 20:32:15 GMT |
|
 |
Sven Carstense #7 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi,
Hi Svan, Thank you again for your great help and tips. (This mail is already on the news groups vc.atl) Finally i am able to debug the service and i must say that it's thanks to you. As you asked me to, i put the line : MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY); in the _tWinMain just before the line : _Module.Start(); I see that i failed in the Run() function on the method CoInitializeSecurity. the HRESULT that i get there is : -2147417831 (80010119) Security must be initialized before any interfaces are marshalled or unmarshalled. It cannot be changed once initialized. There is information about it on the MSDN : INFO: Translating Automation Errors for VB/VBA (Long) , ID: Q186063 So i commented this lines out and now the "start service" actually working: /* CSecurityDescriptor sd; sd.InitializeFromThreadToken(); hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); _ASSERTE(SUCCEEDED(hr)); */ There is solution for it without excluding this code? how important is this security issue? Of course: create your CNotifyEvent object *after* you called CoInitializeSecurity. Now when i stop the service and i debug it, i see that when i stop the sevice, it's try to execute the StopTimer() method of the component (that actually tells it to stop raising the Notify event in the CNotifyEvents class of the service) it probably fialed and distroy the NotifyEventObj object. I tried to catch the error, but i don't know why it ignore any TRY-CATCH that i put, anyway i don't get any failure message at this point. I also though that the reason for this failure is the CoInitialize and CoUninitialize in the CServiceModule::Run(), but after i removed it nothing changed, the problem is still there. Do *not* remove CoInitialize and CoUninitialize from the Run method. That should break your COM calls - if not I'm not sure if I should call you /lucky/, I guess not: Somebody could have called CoInitialize in that thread - which should be in the exe's responsibility, i.d. your responsibility - maybe this /someone/ calls CoUninitialize at another point - breaking your COM calls then. Well catch can only catch what you tell it to catch. If some other type is thrown it will cause an uncaught exception: try { TheBadFunc(); Quote: }
catch(_com_error &e1) // produced by #import generated code { catch _com_error instances} Quote: }
catch(CException* e2) // produced by MFC code { catch MFC specific errors Quote: }
catch(...) { catch everything else - like e.g. access violation... Quote: }
From your mailed code I saw that you once you caught _com_error& and once CException*. But what to catch depends on the classes/methods you use. So if you don't use MFC CExeption* will be of no use. if there are bugs around you could try to catch(...) or if you don't catch it and have debug builds you could watch the call stack to get a clue where the exception was generated. I also tried to understand the smart pointer idea, but i did not really understand it. in my case, the class CNotifyEvents had no interface id - INotifyEvents (as much as i know), and i don't suppose to expose one because this class suppose to be completely internal for catching the sink event and handling it. please correct me if i misunderstand you. As a sink it has to expose at least one interface: the one your event provider will call you on. That seems to be IDispatch, so instead of CComObject<CNotifyEvent> *Global_Object you could use CComPtr<IDispatch> m_spServiceModuleMember. Best regards, Ofir HTH, Sven Hi Ofir, 1) to Debug a service from the start I like the following contruct: inside WinMain or ServiceMain: ... // some code MessageBox(NULL, "a", "b", MB_OK | MB_DEFAULT_DESKTOP_ONLY); ... // the code I wan't to debug When the service starts it will display the messagebox (MB_DEFAULT_DESKTOP_ONLY does the trick!). Now you can attach the de{*filter*} to the service. Put a breakpoint right after the MessageBox call and start debugging. 2) You could store a smart pointer to IUnknown or another interface exposed by CNotifyEvents in your CServiceModule: CComPtr<INotifyEvents> m_spNotifyEvents. In Run() or Start() of your CServiceModule you can then use CComObject<CNotifyEvents> *p just locally to create the instance and store an interface pointer in your smart pointer member with a call to p->QueryInterface(&m_spNotifyEvents). This would also handle ref counting automatically. I hope I got alll your questions. Bye, Sven
Hi Ofir, too fast - I thought you were just asking me by mail so I wrote back by mail without keeping a copy of the reply. To keep all the content in this thread, maybe you could just insert my mail content here. Thanx, Sven
Hi Sven, I want to thank you very much for all your help, i completed the first step and the atl class for the sink event is working (a little different way that i found on the MSDN - you can see it on the attachements) on the test, and i learned a lot about my mistakes from your explanations. So now i have got the class for the sink event and the way to work with it, but on the test. I have read a lot of information about the ATL service (it's my first time with services) on the MSDN, but i have got two types of problems with it: 1. i don't know how to debug it at the first time that i am starting the service, because just after the first time it's running (and get stuck...) i am able to select "DEBUG" from the drop down of the Task Manager Processes list of windows and to set breakpoints in the events. but because it's already ran the major functions that i plan to debug, it's not useful. 2. I am not sure that i know where to put the appropriate methods in the CServiceModule class that the wizard produce for me, but anyway, what i tried did not work: (***) i was able to define it only as global : CComObject<CNotifyEvents> *NotifyEventObj; because this include : #include <atlcom.h> ( for the usage of CComObject in the definition CComObject<CNotifyEvents> *NotifyEventObj; requires the definition of _Module : CServiceModule _Module; I did not find other solution how to define it - CComObject<CNotifyEvents> *NotifyEventObj; - as member of my CNotifyEvents class (***) i wrote this code at the end of the ServiceMain function, it suppose to create an instance (if it has not been created yet) and to execute the InitiateReplication function that suppose to do some database connection job and to execute the AtlAdvise if (NotifyEventObj==NULL) { hr=NotifyEventObj->CreateInstance(&NotifyEventObj); if (FAILED(hr)) { delete NotifyEventObj; } else { NotifyEventObj->InitiateReplication(); } } StartSync(); (***) I wrote this code inline the Handler function. i need it to do the following in case that the user stop the service or start it : inline void CServiceModule::Handler(DWORD dwOpcode) { switch (dwOpcode) { case SERVICE_CONTROL_STOP: SetServiceStatus(SERVICE_STOP_PENDING); PostThreadMessage(dwThreadID, WM_QUIT, 0, 0); StartSync(); //DistroyReplication(); break; case SERVICE_CONTROL_PAUSE: //StopSync(); break; case SERVICE_CONTROL_CONTINUE: StartSync(); break; case SERVICE_CONTROL_INTERROGATE: break; case SERVICE_CONTROL_SHUTDOWN: StopSync(); break; default: LogEvent(_T("Bad service request")); } } when this two functions content is : void CServiceModule::StartSync() { NotifyEventObj->StartTimer(); } void CServiceModule::StopSync() { NotifyEventObj->StopTimer(); } Thank you for any help, Ofir
> Hi, > > I had a look at your attachments. > > You are calling AtlAdvise from within your constructor: m_pReqTimer is still > NULL at that time. > InitiateReplication is a far better place. What's your problem with calling > AtlAdvise at that point? > > GetIDispatch is a helper function from MFC's CCmdTarget to get the > corresponding IDispatch interface from an CCmdTarget derived class - it's > just not available if don't use MFC to implement your COM object. In ATL you > should use GetUnknown(). > > What's still missing is how do you create an instance of CNotifyEvents? It > should be: > > CComObject<CNotifyEvents> *p = NULL; > HRESULT hr = p->CreateInstance(&p); > if(FAILED(hr)) > { > // ouch > delete p; > } > else > { > p->InitiateReplication(); > } > > Bye, > Sven >
> > Hi Sven, > > > > You call AtlAdvise from within a CNotifyEvents instance method? > > > > --yes, i am doing so, why? it did work at the first test
... read more »
|
Sun, 29 Aug 2004 21:16:42 GMT |
|
 |
Sven Carstense #8 / 8
|
 ATL Service - Need to establish sink for a connection point of ActiveX dll
Hi, glad to here that! You're welcome, Sven
|
Sun, 29 Aug 2004 23:12:46 GMT |
|
|
|