question

gigasoft avatar image
0 Votes"
gigasoft asked RLWA32-6355 commented

Two Outlook COM Add-ins and connection points

Hi, I have an application that requires that we install two Outlook COM add-ins. I want to send an event from one COM add-in to the other. So I chose to use ATL connection points. While I can use connection points without a problem in one add-in and capture events, I cannot seem to fire the same event to the other add-in. They are both COM DLL's and are loaded in the same process. I have done this before with other applications, but I seem not to be able to fire an event in one add-in and receive that connection point event in the other add-in within Outlook. Is this a security thing within Outlook? I have tried all the free threaded options, but it seems not to make a difference. Does anybody have any suggestions?

Thanks in advance.

Tom -

c++office-addins-dev
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

General narrative descriptions that basically say "it didn't work" don't provide us with much useful information to assist in diagnosing a problem.

At what point in Outlook processing do your COM add-ins attempt to advise each other to sink events?

How do you ensure that both add-ins have been loaded before you attempt to sink events?

How do they obtain each others IUnknown interfaces?

What COM methods are failing and error codes are received?

Can a test application connect to each of your add-ins and receive events from both of them?

0 Votes 0 ·
gigasoft avatar image
0 Votes"
gigasoft answered RLWA32-6355 edited

Yep, I should have attached some code. Late night :)! I have attached some example code. It fails because if cannot find the connection point connection. I did try to go old school without ATL, but I get the same result.

There is not any failure code, just cannot find connection.

CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); /// <<<< ALWAYS RETURNS 0 FAILS HERE

The code ...

 //////////
 /// DLL  #1 (add-in #1)
 ////////////
    
 // Header
    
 class ATL_NO_VTABLE CSiteDown :
     public CComObjectRootEx<CComSingleThreadModel>,
     public CComCoClass<CSiteDown, &CLSID_SiteDown>,
     public IConnectionPointContainerImpl<CSiteDown>,
     public IDispatchImpl<ISiteDown, &IID_ISiteDown, &LIBID_paddinLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
     public CProxy_ISiteDownEvents<CSiteDown>
 {
 public:
     CSiteDown()
     {
     }
    
     DECLARE_REGISTRY_RESOURCEID(115)
    
    
     BEGIN_COM_MAP(CSiteDown)
         COM_INTERFACE_ENTRY(ISiteDown)
         COM_INTERFACE_ENTRY(IDispatch)
         COM_INTERFACE_ENTRY(IConnectionPointContainer)
     END_COM_MAP()
    
     BEGIN_CONNECTION_POINT_MAP(CSiteDown)
         CONNECTION_POINT_ENTRY(__uuidof(_ISiteDownEvents))
     END_CONNECTION_POINT_MAP()
    
    
     DECLARE_PROTECT_FINAL_CONSTRUCT()
    
     HRESULT FinalConstruct()
     {
         return S_OK;
     }
    
     void FinalRelease()
     {
     }
    
    
 public:
    
     STDMETHOD(EnableErrorState)(VARIANT_BOOL vbEnable);
    
 };
    
 // CPP #1
 STDMETHODIMP CSiteDown::EnableErrorState(VARIANT_BOOL vbEnable)
 {
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
     Fire_EnableEvent(vbEnable);
     return S_OK;
 }
    
 // Events #1
 // Events_CP.h
    
 VOID Fire_EnableEvent(VARIANT_BOOL b)
 {
     T* pT = static_cast<T*>(this);
     int nConnectionIndex;
     CComVariant* pvars = new CComVariant[2];
     int nConnections = m_vec.GetSize();
    
     for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
     {
         pT->Lock();
         ///////////////////////////
         /// DOES NOT RECOGNIZE CONNECTION IN THE ADDIN #2
         ///////////////////////////
         CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);  ///  <<<< ALWAYS RETURNS 0  FAILS HERE
         pT->Unlock();
         IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
         if (pDispatch != NULL)
         {
             pvars[0].vt = VT_BOOL;
             pvars[0].boolVal = b;
             DISPPARAMS disp = { pvars, NULL, 1, 0 };
             pDispatch->Invoke(88, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
         }
     }
     delete[] pvars;
 }
    
 //////////
 /// DLL  #2 (add-in #2)
 ////////////
    
 // Header
    
 BEGIN_COM_MAP(CDown)
     COM_INTERFACE_ENTRY2(IDispatch, IRibbonCallback)
     COM_INTERFACE_ENTRY(_FormRegionStartup)
     COM_INTERFACE_ENTRY(IDown)
     COM_INTERFACE_ENTRY(_IDTExtensibility2)
     COM_INTERFACE_ENTRY(IRibbonExtensibility)
     COM_INTERFACE_ENTRY(IRibbonCallback)
     COM_INTERFACE_ENTRY_IID(__uuidof(paddinLib::_ISiteDownEvents), IExt)
 END_COM_MAP()
    
 CComPtr<paddinLib::ISiteDown> m_spDown;
 DWORD m_dwDownCookie;
    
    
 // CPP
 STDMETHODIMP CDown::Init()
 {
     if (m_spDown == nullptr)
     {
    
         HRESULT h = CoCreateInstance(
             paddinLib::CLSID_SiteDown, NULL, CLSCTX_ALL,
             paddinLib::IID_ISiteDown, reinterpret_cast<LPVOID*>(&m_spDown));
         if (SUCCEEDED(h) && m_spDown)
         {
             h = AtlAdvise(m_spDown, GetUnknown(), paddinLib::DIID__ISiteDownEvents, &m_dwDownCookie);
         }
     }
    
     return S_OK;
 }
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Sorry


This returns 0 >>> int nConnections = m_vec.GetSize();

0 Votes 0 ·

Calling CoCreateInstance just creates another instance of your COM object. This COM object would not be an add-in that was instantiated by Outlook.

Also, the CSiteDown class fails to implement _IDTExtensibility2 so Outlook won't even load this as an add-in.

0 Votes 0 ·
gigasoft avatar image
0 Votes"
gigasoft answered RLWA32-6355 commented

I did a snippet for you. These are two huge add-ins with multiple com components. The key is that when I fire an event from add-in #1 it acts as if there are no connections that were successfully made in add-in #2.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Well, I can't tell what the problem is from the information that has been provided.

I used ATL to create two minimal COM add-ins that loaded into Outlook 2013. Each add-in exposed an event interface. Each add-in added a button to the ribbon to fire an event. Each add-in advised the other to sink events. Both add-ins received events successfully.

203286-first.png

203308-second.png


0 Votes 0 ·
first.png (12.9 KiB)
second.png (13.6 KiB)
gigasoft avatar image
0 Votes"
gigasoft answered RLWA32-6355 commented

I have done tons of these com components. I can definitely tell you it has something to do with Outlook. I will get to the bottom of this and I will let you know what the issue is.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Anything new here?

0 Votes 0 ·