Search code examples
excelvbaribbonx

VBA IRibbonUI.Invalidate causes Excel to crash when used too many times


At the moment I'm working on an Excel document which uses several Add-ins. These Add-ins contain functions that I'm planning on using in other workbooks. One group of functions takes care of some functions for a custom made ribbon:

Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (destination As Any, source As Any, ByVal length As Long)
Private Const ribbonXMLAddress As String = "RibbonSaveLocation"
Private thisRibbon             As IRibbonUI

Public Sub SetRibbonPointer(ByVal ribbon As IRibbonUI)
    ribbonPointer = ObjPtr(ribbon)
End Sub

Public Sub UpdateRibbon()
    currentRibbon.Invalidate
End Sub

Private Property Get currentRibbon() As IRibbonUI
    If thisRibbon Is Nothing Then
        Set thisRibbon = ribbonObject
    End If
    
    Set currentRibbon = thisRibbon
End Property

Private Property Get ribbonPointer() As Long
    ribbonPointer = XMLTool.GetXMLContent(ribbonXMLAddress)
End Property

Private Property Let ribbonPointer(ByVal newPointer As Long)
    XMLTool.ChangeXMLContent ribbonXMLAddress, CStr(newPointer)
End Property

Private Property Get ribbonObject() As Object
    CopyMemory ribbonObject, ribbonPointer, 4
End Property

The code works perfectly fine until I use the function UpdateRibbon too many times (like 6 - 9 times). After that Excel closes and after reopening Excel reports that a problem was found and wants to recover the file.

I've tested the code a few times in the immediate window to be sure and the results were consistent: after validating the ribbon 9 times Excel crashes. I've searched the internet but couldn't find a solution for this problem. To be clear: the ribbon functions are in an add-in and not in the same workbook as the ribbon itself.

Can anyone tell me what causes the crashes or how to prevent them? (Not invalidating the ribbon is not a solution btw :) ) Thanks in advance.


Solution

  • You need to avoid using the CopyMemory call API from the ribbon code:

    Private Property Get ribbonObject() As Object
        CopyMemory ribbonObject, ribbonPointer, 4
    End Property
    

    That is not intended to work this way. Moreover, it is not supported scenario.


    The Fluent UI is described in depth in the following articles: