Accessing CommandBarButton.Picture property the late bound way


I try to read the information of Microsoft Access (Office) CommandBars contained in an *.mdb. I could use Microsoft.Office.Interop.Access for this; however, these PIA assemblies are tied to specific Office versions. Therefore, to be version independent, I do it the late-bound way through C#'s dynamic type. I.e., I have no references to Microsoft Office specific assemblies. The price for this is that the access to the command bars is now weakly typed.

This approach works well, except when I try to access the custom button images. This is a condensed version of my real code to illustrate the problem:

dynamic access =  Activator.CreateInstance(Type.GetTypeFromProgID("Access.Application", true));
// Starts an Access XP (2002) process in my case, but could be any version.

foreach (dynamic commandBar in access.CommandBars) {
    if (!commandBar.BuiltIn) { // Only my menus and toolbars.
        foreach (dynamic control in commandBar.Controls) {
            if (control.Type == (int)MsoControlType.msoControlButton && !control.BuiltInFace) {
                string caption = control.Caption; // Works.
                stdole.IPictureDisp picture = control.Picture; // <==== Throws exception! ====
                // ...

Calling the getter of the CommandBarButton.Picture property throws this exception:

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) at System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult, ExcepInfo& excepInfo, UInt32 argErr, String message)
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at MyApplication.MyMethod in MyApplication.cs:line 64

How can I get the picture avoiding this exception?

Note, this question is not about converting the IPictureDisp object to a System.Drawing.Image object. I already have a solution for this. Also, it makes no difference whether picture is typed as object, dynamic, or IPictureDisp. The property does exist, otherwise I would get the exception 'System.__ComObject' does not contain a definition for 'Picture'.

It is a .NET Framework 4.0 Windows Forms project compiled for x86 (32-bit).

Edit: Switching to Primary Interop Assemblies (PIA) allows strong typing, but does not solve the problem. The exception persists.

Meanwhile I have read more about PIAs. Since .NET Framework 4.0 you can tweak the properties of the assembly reference to make them version independent. Right click on References / Microsoft.Office.Interop.Access and

  • Set Embed Interop Types to True.
  • Set Specific Version to False.

Do this for References / office as well. Therefore I will be switching to PIAs instead of using dynamic.

asked on Stack Overflow Jan 28, 2020 by Olivier Jacot-Descombes • edited Feb 6, 2020 by Olivier Jacot-Descombes

0 Answers

Nobody has answered this question yet.

User contributions licensed under CC BY-SA 3.0