How to implement late bound event handling in case of a VSTO Add-In

If you build a managed component that loads into Office application’s(Word, Excel , PowerPoint) process space, and the managed code uses the PIA (or a custom IA using event delegates) to sink events on the Application object, that application’s instance may encounter problems when used for OLE embedding.

The problems include:

  • Being unable to update object if it is edited twice (in place activated, edited, closed, then activated and edited again) between saves
  • Failure to release lock on object storage, which may inhibit proper closing of the main document file or return an error
  • Crash of Word when one of the above problems occurs and user attempts to edit object again after the reported error

This issue is seen in all current versions of Office (2002, 2003, and 2007).

The problems occur because of the conflicting design behaviours between OLE and .NET over object lifetime. In order to avoid the issue you may try to use the below blog to implement late bound event handling and using IConnectionPointContainer interface.

Excel OLE Embedding Errors if you have Managed Add-In Sinking Application Events in Excel
https://blogs.msdn.com/vsofficedeveloper/pages/excel-ole-embedding-errors-with-managed-addin.aspx

This approach may work well for a COM add-in but in case of a VSTO add-in for Excel you may still encounter an error like-

TargetInvocationException – The interface does not support late bound calls since it does not derive from IDispatch.

The reason for the TargetInvocationException in Excel is that VSTO uses proxy objects (the transparent proxy object always tells Excel that the locale is US English/locale-id 1033 which effectively makes VSTO match VBA behaviour) instead of exposing the application to the actual object model to avoid the Excel locale issue. The Excel locale issue results into following error if you run a VSTO customization for Excel on a machine that has the locale set to something other than US English (locale ID or LCID 1033) –

Exception from HRESULT: 0x800A03EC 

or

Old format or invalid type library.

However introduction of the proxy object causes the  TargetInvocationException in our case because of the inability to typecast the proxy object into Application object.

In order to resolve this error we need to do 2 things -

  1. Set ExcelLocale1033 attribute to false
  2. Mark the assembly as COM Visible

Setting ExcelLocale1033 attribute In the AssemblyInfo.cs file from true to false disables the creation of proxy objects and hence the error which occurred due to typecasting does not occur. Although, this may get you past the above error but you may still encounter an Invalid Case exception.

In order to mark the assmebly as com visible, we can go to AssemblyInfo.cs and set the ComVisible attribute to true.

[assembly: ComVisible(true)]

This is required because the VSTO assemblies are not COM visible by default.

In Word and PowerPoint, you may not face the TargetInvocationException, as there are no proxy objects involved; however, you may get InvalidCastException exception. In that case, you can set the ComVisible attribute for the assembly to true.

One more point to be considered here is that after you set the ExcelLocale1033 to false you are again exposed to the Excel Locale issue. So, if you want to use your add-in across multiple cultures you may want to use one of the workarounds in the article below -

BUG: "Old format or invalid type library" error when automating Excel
https://support.microsoft.com/kb/320369