This blog is only to remind myself of what I've learned (from others or by myself) and only for knowledge sharing. External sources will be clearly stated in [Reference] of each article. I hope this blog won't infringe any copyrights and that it can be useful for interested blog readers.

2008年4月15日 星期二

COM server with Connection Point

 

Purpose:

Demonstrate how COM server (Server Type -- Service (EXE))

callbacks a COM client's API by using Connection Point.

 

!!NOTES:

If COM server's type is DLL, please refer

CodeProject: COM Connection Points

about how to use Connection Point

 

Preface:

(1) VC6 IDE is required

(2) This example only applies to "Service (EXE)" Server Type

(3) This COM server will use Add(..) function to describe how Connection Point is used here

 

Steps:

(1) Create a COM Project

 

(2) Choose Service Type -- Service(EXE)


(3) Add a new ATL Object

 

(4) create a Simple Object

 

(5) Fill in "Names" tab

 

(6) Fill in "Attributes" tab. Remember to check "Support Connection Points"

 

(7) Build to form "connection type" lib first

 

(8) implement Connection Point for CAdd class

 

 

(9) Add _IAddEvents interface

 

(10) Build again

 

(11) fix compile errors by replacing IID__IAddEvents with DIID__IAddEvents

 

(12) Add a method -- Add -- to IAdd interface

 

 

 

(13) Fill in the info of Add method

 

(14) Add a method to _IAddEvents

 

(15) Add a method "ExecutionOver" to _AddEvents interface

 

 

(16) Add a method -- Fire_ExecutionOver(INT Result) -- in CProxy_IAddEvents class

HRESULT Fire_ExecutionOver(INT Result)
{
    CComVariant varResult;
    T* pT = static_cast<T*>(this);
    int nConnectionIndex;
    CComVariant* pvars = new CComVariant[1];
    int nConnections = m_vec.GetSize();
    for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
    {
        pT->Lock();
        CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
        pT->Unlock();
        IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
        if (pDispatch != NULL)
        {
            VariantClear(&varResult);
            pvars[0] = Result;
            DISPPARAMS disp = { pvars, NULL, 1, 0 };

//!!NOTES: 0x1 is an ID to let COM clients tell what to do
            pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
        }
    }
    delete[] pvars;
    return varResult.scode;
}

 

(17) fill in CAdd:Add(int, int) to do "Add" when COM client is calling "Add" function

STDMETHODIMP CAdd::Add(int a, int b)
{
    // TODO: Add your implementation code here

//    Sleep(2000);   // to simulate a long process

    //OK, process over now; let's notify the client

    Fire_ExecutionOver(a+b);

    return S_OK;

}

 

(18) type "Test_COM_Connection_Point.exe -Service" in command mode to make sure it

  can be a service as follows

 

(19) type "services.msc" in command mode and enter service Window

 

(20) activate "Test_COM_Connection_Point.exe " as follows

沒有留言: