几个星期以来,我们一直在与一个问题作斗争,即在少数客户中,我们的 Outlook 插件由于尚未确定的原因而被卸载和禁用。“禁用”是指 Outlook 将以下注册表值从 3 更改为 2,这实际上意味着下次启动时不会加载插件:
HKEY_LOCAL_MACHINE\Software\Microsoft\Office\Outlook\Addins\[OurAddin.sProgID]\LoadBehavior
没有错误消息,也没有任何异常出现在我们的插件自己生成的日志文件中。
我已经找到了专门处理 LoadBehavior 更改问题的以下页面:http: //blogs.msdn.com/vsod/archive/2008/04/22/Troubleshooting-com-add-in-load-failures.aspx
但是,那里提出的所有可能原因似乎都不适用:
- 插件不仅仅列在禁用项目列表中。
IDTExtensibility2
方法中或代码中的其他任何地方都没有未处理的异常。所有代码都包装在 try/catch 等效项中,并且所有异常输出仅通过OutputDebugString
或发送到日志文件中。- 该错误似乎与防病毒软件无关,即它也会在禁用它的情况下发生。
- 禁用所有其他插件也对错误没有影响。
那么,还有什么可能导致 Outlook 禁用插件呢?
更多细节/观察:
- 到目前为止,我们还无法在我们的测试环境中重现该问题,因此我们还无法在问题发生时附加调试器。
- 当我们尝试通过远程支持 (TeamViewer) 观察发生的情况时,该问题永远不会发生。我怀疑这是因为 TeamViewer 使用了一个钩子 DLL,它将自身注入到所有正在运行的进程(包括 Outlook)中,从而影响内存布局、时间、线程顺序等。
- 每当我们编译一个新版本的插件来尝试新的东西时,插件通常会正常工作几个小时甚至几天,但最终会再次被禁用。一旦发生这种情况,所有后续尝试让插件加载到该机器上(通过手动更改 LoadBehavior 值)都将失败(即 LoadBehaviour 将简单地更改回 2),直到我们编译和部署另一个构建(或尝试使用TeamViewer - 见上文)。
- 通常,插件会在 Outlook 启动时立即卸载,但偶尔也会在 Outlook 已经运行一段时间后发生。在这些情况下,日志文件看起来完全不显眼 - 插件只需执行常规关闭步骤,就好像 Outlook 已正常关闭一样。
- 据我所知,从我们的日志文件并通过 SysInternals ProcessMonitor 观察问题,当插件在 Outlook 启动时(而不是在会话期间)被禁用时,DLL 甚至在 COM 对象(即插件)被实例化之前就被卸载(构造函数中的日志消息永远不会出现)。
- 我们将
OutputDebugString
消息放在initialization
部分中(这是一个 Delphi DLL)。当插件无法加载时,它们都不会出现。 只有极少数客户受到此问题的影响。我们有数以万计的安装,我们还没有收到任何关于此的报告。
更新:似乎经常(但并非总是)在插件卸载之前记录的最后一件事是带有文本“OLE 错误 800A01A8”的异常。该异常被我正在使用的框架(Add-in-Express)中内置的全局异常处理程序捕获,并且不会出现在我自己的代码的任何地方,其中每个方法现在都完全包含在
try..catch
. 这通常发生在我从 Inspector 的 Activate 事件处理程序设置 CommandBarButtons 的可见性之后。
所有受影响机器的共同属性:
- Windows XP Professional,最新补丁级别
- Outlook 2003 Professional,最新补丁级别
- 不同版本的 McAfee Virus Scan(尽管禁用它没有效果 - 见上文)
- 用户是本地管理员组的成员
还有一点需要注意,这很可能也很重要(尽管可能没有我最初想的那么重要):
我们正在使用来自第三方供应商的许可/复制保护模块,该模块将已编译的 DLL 包装在“外壳”中,并且仅在运行时解包。自从我发现插件在我们自己的任何代码被执行之前就被卸载了,这一直是我的主要嫌疑人。然而,尽管供应商确认其代码中可能存在未处理的异常,但由保护外壳的特殊调试版本生成的日志文件显示解包过程已成功完成,并且在 Outlook 卸载插件之前控制权已交回受保护的 DLL . 因此,无论是什么导致 Outlook 卸载我们的插件,似乎都发生在保护外壳的初始化完成和我们自己的代码之间。
还有什么想法吗?