we have a add-in in Outlook (VSTO) installed in an environment which has Outlook 2013 and Skype 2013. It has been working successfully until we migrated Skype for Business to version 2016.
Ever since, whenever we try to read anything from the "ContactItem" class (we actually only need a custom field from there), we get the following error (stack trace included) :
"System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Interop.Outlook._ContactItem'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{00063021-0000-0000-C000-000000000046}' failed due to the following error: Library not registered. (Exception from HRESULT: 0x8002801D (TYPE_E_LIBNOTREGISTERED)). at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease) at Microsoft.Office.Interop.Outlook._ContactItem.get_PropertyAccessor()"
After searching we found that there are 2 typeLib versions in [HKEY_CLASSES_ROOT\TypeLib{00062FFF-0000-0000-C000-000000000046}] : 9.5 and 9.6. This is "normal" since we have Outlook 2013 installed with Skype 2016.
If I remove the typeLib 9.6, the Add-In starts to work again, but it breaks Skype. If I remove the TypeLib 9.5, Skype works but Outlook stops working.
Is there a way to force a TypeLib version in VSTO when accessing properties from ContactItem (or other classes from the interop that are defined in 2 typeLibs)?
Or we need to downgrade Skype, or upgrade Outlook?
In an Outlook addin, you cannot access OOM objects on a thread other than the primary thread. Older versions of Outlook can sometimes work, Outlook 2016 raises an error outright.
UPDATE:
Your only options are Extended MAPI (C++ or Delphi only) or Redemption - its RDO family of object is a wrapper around Extended MAPI: to access a contact on a secondary thread, save the value of Namespace.MAPIOBJECT
property in a variable (it points to the IMAPISession Extended MAPI interface) and the value of the contact entry id. On the secondary thread (worker), create an instance of the RDOSession object (that will initialize MAPI on that thread), set the RDOSession.MAPIOBJECT
property to the value saved on the primary thread, call RDOSession.GetMessageFromID.
User contributions licensed under CC BY-SA 3.0