【问题标题】:Periodically getting VBA break mode error messages when loading ribbon controls on PowerPoint start up在 PowerPoint 启动时加载功能区控件时定期收到 VBA 中断模式错误消息
【发布时间】:2019-01-30 03:19:07
【问题描述】:

我为 PowerPoint 创建了一个插件,它从您选择的对象中创建一个对象网格。

加载项在功能区中使用上下文相关控件,因此该控件仅在选择一个或多个形状时可用(否则将显示为灰色)。

当我打开 PowerPoint(启用此加载项)时,我可能会收到以下错误消息:“PowerPoint 无法启动此功能,因为您当前有一个 Visual Basic for Applications 项目处于中断模式。”

当每个自定义控件加载到功能区时,该消息会重复出现(当您对每个错误单击“确定”时,控件会逐渐显示),并且一旦 PowerPoint 启动,这些控件就会出现在功能区中,但显示为灰色,并且不会显示选择形状时激活。

错误很难找出错误:它可能只是消失了,不会重新出现在特定机器上,但随后可能会出现在另一台机器上,用于相同的设置(以及完全相同的加载项代码)。如果此加载项单独加载,则可能会发生这种情况,或者仅在与其他加载项一起加载时才会发生。

当错误消息出现时,我可能会通过注释掉代码部分来查找故障,将其保存并重新添加为 ppam 插件,直到错误消息消失:然后尝试验证我找到了问题的根源,取消注释掉我注释掉的代码,直到错误重新出现 - 除了通常错误不会重新出现。

如果 PowerPoint 以打开的文档启动,则不会出现该错误。此外,该错误可能仅在 PowerPoint 设置为以欢迎屏幕而不是新文档启动时出现。

我当前的 office 版本是:1812(office 365 - desktop),build 11126.20196(但我在其他版本上看到过)和 Windows 10 版本 1803。

我试过了:

  • 将我的所有代码导出到文本文件,然后使用 Rob Bovey 的适用于 PowerPoint 的代码清理器版本将其导入回来:http://www.tushar-mehta.com/powerpoint/vba_codecleaner/index.htm

  • 试图强制显示错误消息以尝试找出错误的可能来源 - 但到目前为止还无法做到这一点:

    • 故意在加载 PowerPoint 时运行的任何代码中插入错误(例如除以零)会导致通常的调试错误消息,而不是我遇到问题的错误消息。

    • 在 Auto_Open、onLoad 和 getEnabled 调用中引入延迟,以尝试获取这些调用中的任何一个,这些调用可能会在 suggestion that Auto_Open and onLoad calls may be fighting with each other 之后重叠,但尽管我可以让 Auto_Open 和 onLoad 调用重叠,this hasn't caused the re-appearance of the error messages .

    • 查看问题是否可能是由于上次关闭 PowerPoint 时出现的问题:我将 PowerPoint 置于中断模式,然后通过任务管理器强制它停止,然后重新启动 PowerPoint - 但未发现任何错误。我还尝试在中断模式 (Excel) 下创建另一个 Office VBA 项目,然后启动 PowerPoint - 再次没有看到错误。

  • 我尝试比较注册表 (HKCU) 何时 PowerPoint 处于中断模式和何时不查看是否可以提供线索 - 但没有什么不同之处。

GridMaker 加载项的 XML 如下所示(在 customUI.xml 中 - 我在 Visual Studio 中使用 Open XML Package Editor 扩展打开了 pptm 文件):

<customUI onLoad="GMApplicationEventsModule.gmRibbonUI_onLoad" xmlns="http://schemas.microsoft.com/office/2006/01/customui" xmlns:nsCommtap="CommtapNamespace">
  <ribbon startFromScratch="false">
    <tabs>
      <tab idMso="TabHome">
        <group id="gridMakerGroup" label="Grid Maker">
          <button id="gmMakeGrid"
                  label="Make Into Grid"
                  imageMso="TableInsert"
                  size="normal"
                  onAction="MainModule.makeGrid"
                  getEnabled="GMApplicationEventsModule.gm_GetEnabled" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

GMApplicationEventsModule 如下所示:

Option Explicit

Private m_oMyRibbon As IRibbonUI
Private m_boolShapeSelected As Boolean
Private m_oAppEvents As CGMApplicationEvents

Public Function get_m_oMyRibbon() As IRibbonUI
  Set get_m_oMyRibbon = m_oMyRibbon
End Function

Public Sub set_m_boolShapeSelected(value As Boolean)
  m_boolShapeSelected = value
End Sub

Public Function get_m_boolShapeSelected() As Boolean
  get_m_boolShapeSelected = m_boolShapeSelected
End Function

Public Sub gm_GetEnabled(control As IRibbonControl, ByRef returnedVal)
  returnedVal = True
  If control.Id = "gmMakeGrid" Then
    returnedVal = GMApplicationEventsModule.get_m_boolShapeSelected
  End If
End Sub

Public Sub gmRibbonUI_onLoad(Ribbon As IRibbonUI)
  Set m_oMyRibbon = Ribbon
End Sub

Public Sub Auto_Open()
  If m_oAppEvents Is Nothing Then
    Set m_oAppEvents = New CGMApplicationEvents
  End If
  Set m_oAppEvents.App = Application
End Sub

类 CGMApplicationEvents:

Option Explicit

Public WithEvents App As Application

Private Sub App_WindowSelectionChange(ByVal Sel As Selection)

  If Application.ActiveWindow.Selection.Type <> ppSelectionShapes Then
    GMApplicationEventsModule.set_m_boolShapeSelected False
  Else
    GMApplicationEventsModule.set_m_boolShapeSelected True
  End If

  If Not GMApplicationEventsModule.get_m_oMyRibbon Is Nothing Then
    Dim oRibbon As IRibbonUI
    Set oRibbon = GMApplicationEventsModule.get_m_oMyRibbon
    oRibbon.InvalidateControl "gmMakeGrid"
  End If

End Sub

我还有另外两个看起来像这样的加载项。 gmMakeGrid 按钮(上图)上的 onAction 运行一些代码,该代码从形状选择中创建形状网格。其他两个加载项仅在单击其按钮时显示一条消息。但是,如果此处显示的代码只是链接到显示消息框,则应该有可能(或不可能 - 因为错误似乎是间歇性的)。

显示错误信息

我现在可以显示错误消息(“PowerPoint 无法启动此功能...”),这也表明错误的来源可能源自错误所在的加载项以外的其他位置可见。

我有一个已启用的加载项 - app1-basic(使用上述代码)。我有第二个宏 (app2-basic.pptm) 文件(也如上所述),其中我在 onLoad 过程中放置​​了一个“停止”语句。关闭 PowerPoint 后,打开 app2-basic.pptm。打开时,VBE 将打开,代码执行将在 stop 语句处停止。现在关闭 PowerPoint(通过单击部分打开的 PowerPoint 中的“X”)。这将显示错误消息。

错误消息似乎已被触发,因为 PowerPoint 正在尝试调用加载项中的 getEnabled 过程,但由于打开的宏已将其置于中断模式而无法调用。日志记录似乎支持这一点:

时间 时间刻度 VBA 项目模块 程序 注释 在 app2-basic onLoad 中停止,它作为 pptm(不是插件)打开,启用了另一个插件(app1-basic) 25/02/19 15:17:58:258 158,650,603,696 app1-basic ApplicationEventsModule Auto_Open 调用 25/02/19 15:17:58:258 158,650,619,479 app1-basic ApplicationEventsModule Auto_Open 已完成 25/02/19 15:17:59:259 158,653,089,479 app1-basic ApplicationEventsModule set_m_boolShapeSelected 已调用 25/02/19 15:17:59:259 158,653,105,936 app1-basic ApplicationEventsModule get_m_oMyRibbon 调用 25/02/19 15:17:59:259 158,653,421,625 app1-basic ApplicationEventsModule gmRibbonUI_onLoad 被调用。 25/02/19 15:17:59:259 158,653,477,892 app1-basic ApplicationEventsModule gmRibbonUI_onLoad 已完成 25/02/19 15:17:59:259 158,653,560,560 app2-basic ApplicationEventsModule gmRibbonUI_onLoad 被调用。 正常打开然后关闭 - app1 - 没有错误 25/02/19 15:34:45:245 161,505,047,523 app1-basic ApplicationEventsModule Auto_Open 调用 25/02/19 15:34:45:245 161,505,061,039 app1-basic ApplicationEventsModule Auto_Open 已完成 25/02/19 15:34:54:254 161,531,088,269 app1-basic ApplicationEventsModule gmRibbonUI_onLoad 被调用。 25/02/19 15:34:54:254 161,531,110,752 app1-basic ApplicationEventsModule gmRibbonUI_onLoad 已完成 25/02/19 15:34:54:254 161,531,169,707 app1-basic ApplicationEventsModule app1_GetEnabled 调用:Control.id:app1ShapeSelectedMsg 25/02/19 15:34:54:254 161,531,200,726 app1-basic ApplicationEventsModule get_m_boolShapeSelected 已调用 25/02/19 15:34:54:254 161,531,215,706 app1-basic ApplicationEventsModule app1_GetEnabled 已完成:Control.id:app1ShapeSelectedMsg

更多内容:

  • 有时,在出现多轮错误然后更正错误后,在加载没有错误的加载项时会出现此错误消息。我仍然无法想出导致这种情况发生的可重复操作序列。

  • 看起来错误可能是由其他地方引起的,而不是由于错误而无法正确加载的加载项。该错误似乎也可能是由于 PowerPoint 的打开状态存在问题 - 可能是由于上次关闭时遇到的问题。

演示错误的代码

Full code which produces this error message from time to time

【问题讨论】:

  • 我为两个最小的加载项添加了一个代码链接,它们将显示错误消息(不时)。

标签: vba powerpoint ribbonx


【解决方案1】:

我昨天也遇到了同样的情况,根据您的描述,我们可能遇到过类似的情况。

当你参考例如你可以得到这个错误。当前演示文稿的路径或加载项加载时的当前选择...即,没有打开的演示文稿,并且通过扩展可能没有当前选择。

我能够通过编写一个小函数来追踪触发错误的确切代码行,该函数会弹出一个带有一些描述性文本的消息框,并且可以选择标题中当前子例程的名称:

Public Sub UberMsg(sMsgString As String, Optional sRoutine As String = "Debug Msg")
    If UberMsg Then
        Call MsgBox(sMsgString, vbOKOnly, sRoutine)
    End If
End Sub

将名为 sRoutine 的字符串和名为 UberMsg 的布尔值声明为全局变量(设置为 True)

然后在我的 AutoOpen 子和从中调用的子中的各个点:

这个,曾经的例行乞讨:

sRoutine = "{the current procedure name}"

然后在每个可疑代码点之前复制/粘贴/编辑它:

UberMsg "AppInit entry point", sRoutine

保存 PPAM 和重新测试只需要几次迭代即可找到问题区域并修复它。

我会将 UberMsg 布尔值设置为 false 并保留所有这些以防以后需要。

【讨论】:

  • 我试图通过在 Auto_Open、getEnabled 和 onLoad 调用中引用 Application.ActiveWindow.Selection.TypeApplication.ActivePresentation.Path 来重新出现错误消息,但未能让错误消息重新出现PowerPoint 将打开(实际上没有出现错误消息)。记录到文件显示这些错误发生的位置 Auto_Open(或其他)函数的其余部分被跳过。仅当您随后关闭 PowerPoint 而不打开/创建文档时才会出现错误消息。您是否能够让错误消息在它消失后重新出现?
  • @neilt17 不,一旦发生错误并且我将其关闭,一切都按预期工作。就我而言,这与在 PPT 仍在初始化时访问 ActivePresentation.Path 有关(因此没有活动演示),或者与所谓的路径字符串的后续处理有关(但实际上是 null)。
  • 谢谢你。澄清一下,如果您要放回您看到错误消息(“PowerPoint 无法启动此功能,因为...”)的 ppam 版本,您这样做还是看不到该错误消息?
  • 问题 PPAM 每次启动 PPT 并加载加载项(在本例中是通过注册表中的条目)时都会产生错误消息。
  • 太好了。令人沮丧的是这个问题是我可以一直处理它直到它消失 - 但是当我重新引入据称有问题的代码时,问题不会再次出现:并重新加载早期版本的 ppam产生错误不再产生它们。我不相信我曾经找到错误的根源。在我没有看到的启动过程中是否可能发生其他事情,并且可能需要对某些事情进行一些清理(通过 Auto_Open 或 onLoad 说) - 但是什么?你能发布一些总是会产生这个错误的代码吗?
【解决方案2】:

不幸的是,我无法做到这一点,所以这个问题总是会出现 - 无论我有什么设置,问题似乎都是随机出现并随机消失。

我的解决方案是完全回避这个问题,不使用 Auto_Open(如果不使用 Auto_Open,这个问题永远不会发生)并且不使用 _onLoad which can also be problematic。这意味着按钮将始终可用,即使在它们不起作用的上下文中也是如此。

为了使这种情况对用户更加友好(不仅仅是弹出一些令人讨厌的消息框错误来告诉人们他们点击了无效按钮),我已经安排了它,以便如果用户选择一个按钮不适用于当前上下文 - 例如,操作要求他们选择一些文本以使其工作,但他们没有 - 将弹出一个非模式对话框,其中包含他们需要做什么才能获得按钮的说明工作(例如选择一些文本)加上功能区组中按钮的精确副本,其中按钮根据上下文正确启用/禁用自身。

我创建了这些按钮,方法是在每个按钮的三种状态(悬停、启用、禁用)中裁剪每个按钮的屏幕截图,并在用户表单中将它们层叠在一起。我使用app_windowselectionchange事件更改相关按钮的zorder,以便选择相应的东西启用的按钮到顶部,并且鉴于选择正确的东西,按钮的悬停版本将到顶部当鼠标悬停在它上面时(用户窗体中的 MouseMove 触发器) - 这也是按钮的版本,单击时将触发任何代码。

我认为这不是一个糟糕的解决方案,因为用户可以获得有关何时可以使用按钮的更多信息,并且他们可以显示一个对话框,该对话框的工作方式与功能区的工作方式相同,如果他们愿意的话。我们的按钮组非常小(不超过四个按钮),因此对话框也非常小,易于显示和推开 - 对于其中包含大量按钮的组来说可能不太令人满意。

【讨论】:

    猜你喜欢
    • 2012-03-27
    • 1970-01-01
    • 2023-03-06
    • 2021-06-13
    • 2012-08-15
    • 1970-01-01
    • 2014-11-22
    • 1970-01-01
    • 2013-07-13
    相关资源
    最近更新 更多