PowerPoint Add-In-Verlust von RibbonUI

Ich habe Probleme, die Ursache eines Fehlers in einem PPT-Add-In zu identifizieren, das auf ungefähr 40 Endbenutzer verteilt ist.

Problem Verlust des Ribbon-Status / Verlust des RibbonUI-Objekts.

Für einige Benutzer kann dasRib Objekt wirdNothing.

Benutzer versichern mir, dass sie keine Laufzeit- oder Skriptfehler erhalten (von COM-Objekten, die wir auch über dieses Add-In aufrufen). Ein unbehandelter Fehler, wenn der Benutzer auf @ klickEnd würde voraussichtlich den Staatsverlust verursachen.

Keiner der Benutzer konnte das Szenario, das den beobachteten Fehler verursacht, zuverlässig reproduzieren. Aus diesem Grund ist die Fehlersuche sehr schwierig. Ich hoffe gegen die Hoffnung, dass es etwas Offensichtliches gibt, das ich vermisse oder das ich nicht erwartet habe.

Wie ich momentan mit Verlust oder RibbonUI umgehe

Um dem entgegenzuwirken, speichere ich den Objektzeiger auf das Menüband inDRE Orte, das scheint mir übertrieben, aber es ist anscheinend immer noch nicht ausreichend:

Ein Klassenobjekt mit dem NamencbRibbon hat eine Eigenschaft.RibbonUI welches zugewiesen ist;Set cbRibbon.RibbonUI = Rib während des BändchensonLoad Rückrufprozedur. Also haben wir einbyRef Kopie des Objekts selbst. Wenn das Band nichts ist, kann ich theoretischSet rib = cbRibbon.RibbonUI und das funktioniert, wenncbRibbon Objekt liegt ebenfalls außerhalb des Gültigkeitsbereichs.DascbRibbon Objekt hat Eigenschaft.Pointer welches zugewiesen ist:cbRibbon.Pointer = ObjPtr(Rib).A CustomDocumentProperty namens "RibbonPointer" wird auch verwendet, um eine Referenz auf den Objektzeiger zu speichern. Hinweis: Dies bleibt auch über den Staatsverlust hinaus bestehen)

So können Sie sehen, dass ich einige Überlegungen angestellt habe, um die Art und Weise des Speicherns dieses Zeigers so zu replizieren, wie man ihn in einem verborgenen Arbeitsblatt / Bereich in Excel speichern könnte.

Zusätzliche Informatio

Ich kann anhand der robusten clientseitigen Protokollierung feststellen, dass dieser Fehler normalerweise, jedoch nicht immer, während der folgenden Prozedur auftritt, die zum Aktualisieren / Ungültigmachen des Menübands und seiner Steuerelemente verwendet wird.

Diese Prozedur wird jedes Mal aufgerufen, wenn ich das Menüband oder einen Teil seiner Steuerelemente dynamisch aktualisieren muss:

Call RefreshRibbon(id)

Der Fehler scheint zu (manchmal kann ich das nicht genug betonen: der Fehlerkann nich bei Bedarf repliziert werden) während einer vollständigen Aktualisierung erfolgen, die wie folgt aufgerufen wird:

Call RefreshRibbon("")

Dies ist die Prozedur, die die Ungültigerklärung vornimmt:

Sub RefreshRibbon(id As String)

    If Rib Is Nothing Then
        If RibbonError(id) Then GoTo ErrorExit
    End If

    Select Case id
        Case vbNullString, "", "RibbonUI"
            Call Logger.LogEvent("RefreshRibbon: Rib.Invalidate", Array("RibbonUI", _
                                            "Ribbon:" & CStr(Not Rib Is Nothing), _
                                            "Pointer:" & ObjPtr(Rib)))
            Rib.Invalidate

        Case Else
            Call Logger.LogEvent("RefreshRibbon: Rib.InvalidateControl", Array(id, _
                                            "Ribbon:" & CStr(Not Rib Is Nothing), _
                                            "Pointer:" & ObjPtr(Rib)))
            Rib.InvalidateControl id
    End Select

    Exit Sub

ErrorExit:

End Sub

ie Sie sehen können, ist das allererste, was ich in diesem Verfahren tue, das Testen desRib Objekt fürNothing -ness. Wenn dies zu @ ausgewertet wiTrue, dann ist das RibbonUI-Objekt irgendwie verloren gegangen.

Die Fehlerfunktion versucht dann, das Menüband erneut zu instanziieren:zuers voncbRibbon.RibbonUI, dann von dercbRibbon.Pointer und wenn beide fehlschlagen, dann von derCustomDocumentProperties("RibbonPointer") Wert. Wenn keiner dieser Vorgänge erfolgreich ist, wird ein schwerwiegender Fehler angezeigt und der Benutzer wird aufgefordert, die PowerPoint-Anwendung zu schließen. Wenn einer dieser Vorgänge erfolgreich ist, wird das Menüband programmgesteuert neu geladen und alles funktioniert weiterhin.

Hier ist der Code für diese Prozedur. Beachten Sie, dass es mehrere andere Prozeduren aufruft, für die ich keinen Code eingefügt habe. Dies sind Hilfs- oder Loggerfunktionen. Das.GetPointer -Methode ruft tatsächlich die WinAPI aufCopyMemory Funktion zum erneuten Laden des Objekts von seinem Zeigerwert.

Function RibbonError(id As String) As Boolean
'Checks for state loss of the ribbon
Dim ret As Boolean

If id = vbNullString Then id = "RibbonUI"

Call Logger.LogEvent("RibbonError", Array("Checking for Error with Ribbon" & vbCrLf & _
                                            "id: " & id, _
                                            "Pointer: " & ObjPtr(Rib), _
                                            "cbPointer: " & cbRibbon.Pointer))

If Not Rib Is Nothing Then
    GoTo EarlyExit
End If

On Error Resume Next

    'Attempt to restore from class object:
    Set Rib = cbRibbon.ribbonUI

    'Attempt to restore from Pointer reference if that fails:
    If Rib Is Nothing Then
        'Call Logger.LogEvent("Attempt to Restore from cbRibbon", Array(cbRibbon.Pointer))
        If Not CLng(cbRibbon.Pointer) = 0 Then
            Set Rib = cbRibbon.GetRibbon(cbRibbon.Pointer)
        End If
    End If

    'Attempt to restore from CDP

    If Rib Is Nothing Then
        'Call Logger.LogEvent("Attempt to Restore from CDP", Array(MyDoc.CustomDocumentProperties("RibbonPointer")))
        If HasCustomProperty("RibbonPointer") Then
            cbRibbon.Pointer = CLng(MyDoc.CustomDocumentProperties("RibbonPointer"))
            Set Rib = cbRibbon.GetRibbon(cbRibbon.Pointer)

        End If
    End If

On Error GoTo 0

If Rib Is Nothing Then
    Debug.Print "Pointer value was: " & cbRibbon.Pointer
    'Since we can't restore from an invalid pointer, erase this in the CDP
    ' a value of "0" will set Rib = Nothing, anything else will crash the appliation
    Call SetCustomProperty("RibbonPointer", "0")
Else
    'Reload the restored ribbon:
    Call RibbonOnLoad(Rib)

    Call SetCustomProperty("RibbonPointer", ObjPtr(Rib))

    cbRibbon.Pointer = ObjPtr(Rib)
End If

'Make sure the ribbon exists or was able to be restored
ret = (Rib Is Nothing)

If ret Then
    'Inform the user
    MsgBox "A fatal error has been encountered. Please save & restart the presentation", vbCritical, Application.Name
    'Log the event to file
    Call Logger.LogEvent("RibbonError", Array("FATAL ERROR"))

    Call ReleaseTrap

End If

EarlyExit:

    RibbonError = ret

End Function

All dies funktioniert in der Theorie perfekt und in der Tat kann ich direkttöte run-time (durch Aufrufen desEnd statement oder anders) und diese Prozeduren setzen das Menüband wie erwartet zurück.

Also, was fehle ich?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage