Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. COM
  4. Get Events from an COM Server

Get Events from an COM Server

Scheduled Pinned Locked Moved COM
questionc++comsysadminhelp
11 Posts 2 Posters 3 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Juergen_80

    Hi All, now I get connected in my main.cpp file to the server. I hope this will be correct. But how can I get now an event from the server? The server sends some events. I can see that because an Message Dialog will be opened from the server. Now my questions are the following: a) Is the code until now correct? Is it possible to make a test if I get the correct connection or anything else? b) How can I get in the main.cpp an event (OnShowMessageDlg) or any message from the server? Do I need to add something to the sink class? c) Must I add something in the Sink class to get the an event in the invoke function? Or how should this work? Let me know If you need any more information. Once more, thanks for any help. Juergen main.cpp File

    CComPtr<ICWOLE2> tCWOLE;
    HRESULT hr;
    hr = CoInitialize(0);

    hr = CoCreateInstance(CLSID_CWOLEv2, 0, CLSCTX_LOCAL_SERVER, IID_ICWOLE2, (void**)&tCWOLE);
    IConnectionPointContainer * pConnPtContainer;
    hr = tCWOLE->QueryInterface(IID_IConnectionPointContainer,(void**)&pConnPtContainer);
    if(FAILED(hr)){
    CoUninitialize();
    return false;
    }
    CComPtr<IConnectionPoint> ICPoint;
    hr = pConnPtContainer->FindConnectionPoint(DIID_ICWOLEEvents,&m_pConnectionPoint);
    if(FAILED(hr)){
    CoUninitialize();
    return false;
    }

    m_sink = new CSink;
    LPUNKNOWN pUnk = NULL;
    m_sink->QueryInterface(IID_IUnknown,(void**)&pUnk);
    hr = m_pConnectionPoint->Advise(pUnk,&m_sink->cookie);
    if(FAILED(hr)){
    CoUninitialize();
    return false;
    }
    pConnPtContainer->Release();
    .
    .
    .
    // Here I must get the event from the COM Server, but how can this be done???
    // How can I test if I get the information from the correct class??
    .
    .
    .

    m_pConnectionPoint->Unadvise(m_sink->cookie);
    m_pConnectionPoint->Release();
    m_sink->Release();

    CSink.h

    class CSink : public ICWOLEEvents
    {
    public:

    	CSink::CSink() {m\_refCount = 1, cookie = 0;}
    	CSink::~CSink()	{}
    	
    	STDMETHODIMP QueryInterface(REFIID riid, void \*\* ppvObj); //HRESULT \_stdcall
    	STDMETHODIMP\_(ULONG) AddRef();  // Note the underscore
    	STDMETHODIMP\_(ULONG) Release();
    
    	
    	STDMETHODIMP GetTypeInfoCount(UINT \*iTInfo);
    	STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo \*\*ppTInfo);
    	STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR \*\*rgszNames, UINT cNames,  LCID lcid, DISPID \*rgDispId);
    	STDMETHODIMP Invoke(DISPID dispIdMember, 
    						REFIID riid, 
    						LCID lcid,
    						WORD wFlags, DISPPARAMS
    
    S Offline
    S Offline
    Stuart Dootson
    wrote on last edited by
    #2

    Yes, you need to add code into the Invoke methods that looks at the dispid that's passed and maps that to the method you need to call. In addition, you need to unpack the parameter values from the struct pointed at by pDispParams. Also, that thread needs to be in a window message dispatch loop - my understanding is that COM method calls are passed from other threads and processes into your thread using windows messages. I know you can't/don't want to use ATL and I can totally understand that...but ATL does make this sort of thing REALLY easy :-)

    Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

    J 1 Reply Last reply
    0
    • S Stuart Dootson

      Yes, you need to add code into the Invoke methods that looks at the dispid that's passed and maps that to the method you need to call. In addition, you need to unpack the parameter values from the struct pointed at by pDispParams. Also, that thread needs to be in a window message dispatch loop - my understanding is that COM method calls are passed from other threads and processes into your thread using windows messages. I know you can't/don't want to use ATL and I can totally understand that...but ATL does make this sort of thing REALLY easy :-)

      Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

      J Offline
      J Offline
      Juergen_80
      wrote on last edited by
      #3

      Hi Stuart, thanks a lot for your reply. Do you know if there will be an example about the invoke theme? I didn't know how this function will/must be called and how my functions then will be called / how I can get a message from the COM server above this invoke functions. I know and I heared also from other people :) that it will be easier to work with ATL. But in this project I can't use ATL.

      S 1 Reply Last reply
      0
      • J Juergen_80

        Hi Stuart, thanks a lot for your reply. Do you know if there will be an example about the invoke theme? I didn't know how this function will/must be called and how my functions then will be called / how I can get a message from the COM server above this invoke functions. I know and I heared also from other people :) that it will be easier to work with ATL. But in this project I can't use ATL.

        S Offline
        S Offline
        Stuart Dootson
        wrote on last edited by
        #4

        OK - the Invoke method is called when an event is raised by the server. It will tell you which method it's calling using the dispidMember parameter. The parameters to the call will be in the structure pointed at by pdispparams. You can pass back a result in pvarResult. So, you could implement your Invoke using a switch statement and parameter transformation like this:

        STDMETHODIMP CSink::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
        WORD wFlags, DISPPARAMS* pDispParams,
        VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
        UINT* puArgErr)
        {

        if ((riid != IID_NULL))
        return E_INVALIDARG;

        HRESULT hr = S_OK; // Initialize

        switch (dispIdMember)
        {
        case 1: // OnConfigurationApply
        // Here we need to verify that the parameters passed are what we expect (a VARIANT_BOOL*)
        // then call the OnConfigurationApply with these passed parameters
        if (pDispParams->cArgs != 1) return E_INVALIDARG;
        if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL|VT_BYREF) return E_INVALIDARG;
        OnConfigurationApply(V_BOOLREF(&pDispParams->rgvarg[0]));
        break;
        case 2: // OnShowMessageDlg
        // Do as for OnConfigurationApply
        break;
        }

        return hr;
        }

        HTH!

        Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

        J 1 Reply Last reply
        0
        • S Stuart Dootson

          OK - the Invoke method is called when an event is raised by the server. It will tell you which method it's calling using the dispidMember parameter. The parameters to the call will be in the structure pointed at by pdispparams. You can pass back a result in pvarResult. So, you could implement your Invoke using a switch statement and parameter transformation like this:

          STDMETHODIMP CSink::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
          WORD wFlags, DISPPARAMS* pDispParams,
          VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
          UINT* puArgErr)
          {

          if ((riid != IID_NULL))
          return E_INVALIDARG;

          HRESULT hr = S_OK; // Initialize

          switch (dispIdMember)
          {
          case 1: // OnConfigurationApply
          // Here we need to verify that the parameters passed are what we expect (a VARIANT_BOOL*)
          // then call the OnConfigurationApply with these passed parameters
          if (pDispParams->cArgs != 1) return E_INVALIDARG;
          if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL|VT_BYREF) return E_INVALIDARG;
          OnConfigurationApply(V_BOOLREF(&pDispParams->rgvarg[0]));
          break;
          case 2: // OnShowMessageDlg
          // Do as for OnConfigurationApply
          break;
          }

          return hr;
          }

          HTH!

          Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

          J Offline
          J Offline
          Juergen_80
          wrote on last edited by
          #5

          The problem I have before is that the Invoke Function will not be called. What must I do that this function will be called from the Server when an event is raised? I can see that an event is raised from the server because an dialog will be opended. But the invoke function will not be called.

          S 1 Reply Last reply
          0
          • J Juergen_80

            The problem I have before is that the Invoke Function will not be called. What must I do that this function will be called from the Server when an event is raised? I can see that an event is raised from the server because an dialog will be opended. But the invoke function will not be called.

            S Offline
            S Offline
            Stuart Dootson
            wrote on last edited by
            #6

            Your code all looks reasonable - I presume you've set a breakpoint in your Invoke method to see if it gets called? I'd also set breakpoints on your AddRef, QueryInterface methods and see if they get called when you call the connection point's Advise method - that's how you tell the server about your event handler.

            Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

            J 1 Reply Last reply
            0
            • S Stuart Dootson

              Your code all looks reasonable - I presume you've set a breakpoint in your Invoke method to see if it gets called? I'd also set breakpoints on your AddRef, QueryInterface methods and see if they get called when you call the connection point's Advise method - that's how you tell the server about your event handler.

              Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

              J Offline
              J Offline
              Juergen_80
              wrote on last edited by
              #7

              I set now also some breakpoints in the AddRef and QueryInterface Methods. These methods will be called. Only the Invoke function will not be called. Do you know what I can do to test if I did something wrong or if the COM server works correct?

              S 1 Reply Last reply
              0
              • J Juergen_80

                I set now also some breakpoints in the AddRef and QueryInterface Methods. These methods will be called. Only the Invoke function will not be called. Do you know what I can do to test if I did something wrong or if the COM server works correct?

                S Offline
                S Offline
                Stuart Dootson
                wrote on last edited by
                #8

                Suddenly realised what your problem could well be. The server could be asking for your event handler's dispinterface methods by name - in which case you would need to implement GetIDsOfNames. Or it could be asking for your class's type-information, in order to determine what methods and associated parameters are available. I think you need to investigate (with breakpoints) whether the othe r IDispatch methods are called. If they are, then as you don't implement them, the server will (as a result) decide not to call your IDispatch::Invoke method. All these details, and the pain of implementation, are why I use ATL - I fully accept that you can't use ATL - I sympathize with your predicament!

                Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                J 1 Reply Last reply
                0
                • S Stuart Dootson

                  Suddenly realised what your problem could well be. The server could be asking for your event handler's dispinterface methods by name - in which case you would need to implement GetIDsOfNames. Or it could be asking for your class's type-information, in order to determine what methods and associated parameters are available. I think you need to investigate (with breakpoints) whether the othe r IDispatch methods are called. If they are, then as you don't implement them, the server will (as a result) decide not to call your IDispatch::Invoke method. All these details, and the pain of implementation, are why I use ATL - I fully accept that you can't use ATL - I sympathize with your predicament!

                  Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                  J Offline
                  J Offline
                  Juergen_80
                  wrote on last edited by
                  #9

                  I tried it now with the breakpoints. The functions QueryInterface / AddRef and Release (IUnknown) will be called. But all the four IDispatch methods (GetTypeInfoCount / GetTypeInfo / GetIDsOfNames / Invoke) will not be called. So now if I understood you correct, I must implement (call the method) GetIDsOfNames by myself? I tried the implementation of the method GetIDsOfNames a little bit but my application crashed down anytime. Please give me a note if I understood you correctly that the solution must be to implement this function. If so, I must search for some better examples about that and try it again. :-D Thanks for your help.

                  S 1 Reply Last reply
                  0
                  • J Juergen_80

                    I tried it now with the breakpoints. The functions QueryInterface / AddRef and Release (IUnknown) will be called. But all the four IDispatch methods (GetTypeInfoCount / GetTypeInfo / GetIDsOfNames / Invoke) will not be called. So now if I understood you correct, I must implement (call the method) GetIDsOfNames by myself? I tried the implementation of the method GetIDsOfNames a little bit but my application crashed down anytime. Please give me a note if I understood you correctly that the solution must be to implement this function. If so, I must search for some better examples about that and try it again. :-D Thanks for your help.

                    S Offline
                    S Offline
                    Stuart Dootson
                    wrote on last edited by
                    #10

                    Have a look more closely at what interfaces are being asked for in QueryInterface. The fact that your IDispatch methods aren't being called means that implementing GetIDsOfNames isn't going to help - you need to work out what the server's actually trying to access on your event handler object.

                    Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                    1 Reply Last reply
                    0
                    • J Juergen_80

                      Hi All, now I get connected in my main.cpp file to the server. I hope this will be correct. But how can I get now an event from the server? The server sends some events. I can see that because an Message Dialog will be opened from the server. Now my questions are the following: a) Is the code until now correct? Is it possible to make a test if I get the correct connection or anything else? b) How can I get in the main.cpp an event (OnShowMessageDlg) or any message from the server? Do I need to add something to the sink class? c) Must I add something in the Sink class to get the an event in the invoke function? Or how should this work? Let me know If you need any more information. Once more, thanks for any help. Juergen main.cpp File

                      CComPtr<ICWOLE2> tCWOLE;
                      HRESULT hr;
                      hr = CoInitialize(0);

                      hr = CoCreateInstance(CLSID_CWOLEv2, 0, CLSCTX_LOCAL_SERVER, IID_ICWOLE2, (void**)&tCWOLE);
                      IConnectionPointContainer * pConnPtContainer;
                      hr = tCWOLE->QueryInterface(IID_IConnectionPointContainer,(void**)&pConnPtContainer);
                      if(FAILED(hr)){
                      CoUninitialize();
                      return false;
                      }
                      CComPtr<IConnectionPoint> ICPoint;
                      hr = pConnPtContainer->FindConnectionPoint(DIID_ICWOLEEvents,&m_pConnectionPoint);
                      if(FAILED(hr)){
                      CoUninitialize();
                      return false;
                      }

                      m_sink = new CSink;
                      LPUNKNOWN pUnk = NULL;
                      m_sink->QueryInterface(IID_IUnknown,(void**)&pUnk);
                      hr = m_pConnectionPoint->Advise(pUnk,&m_sink->cookie);
                      if(FAILED(hr)){
                      CoUninitialize();
                      return false;
                      }
                      pConnPtContainer->Release();
                      .
                      .
                      .
                      // Here I must get the event from the COM Server, but how can this be done???
                      // How can I test if I get the information from the correct class??
                      .
                      .
                      .

                      m_pConnectionPoint->Unadvise(m_sink->cookie);
                      m_pConnectionPoint->Release();
                      m_sink->Release();

                      CSink.h

                      class CSink : public ICWOLEEvents
                      {
                      public:

                      	CSink::CSink() {m\_refCount = 1, cookie = 0;}
                      	CSink::~CSink()	{}
                      	
                      	STDMETHODIMP QueryInterface(REFIID riid, void \*\* ppvObj); //HRESULT \_stdcall
                      	STDMETHODIMP\_(ULONG) AddRef();  // Note the underscore
                      	STDMETHODIMP\_(ULONG) Release();
                      
                      	
                      	STDMETHODIMP GetTypeInfoCount(UINT \*iTInfo);
                      	STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo \*\*ppTInfo);
                      	STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR \*\*rgszNames, UINT cNames,  LCID lcid, DISPID \*rgDispId);
                      	STDMETHODIMP Invoke(DISPID dispIdMember, 
                      						REFIID riid, 
                      						LCID lcid,
                      						WORD wFlags, DISPPARAMS
                      
                      J Offline
                      J Offline
                      Juergen_80
                      wrote on last edited by
                      #11

                      Stuart, thanks for your help. Now it seems to work. The problem was that the Connection (Advise) must be done before I open the programm. If I do this Advise after the program start I didn't get any events.

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups