18

几个星期以来,我们一直在与一个问题作斗争,即在少数客户中,我们的 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 卸载我们的插件,似乎都发生在保护外壳的初始化完成和我们自己的代码之间。

还有什么想法吗?

4

5 回答 5

5

多年来,我的公司一直在忍受听起来与您所看到的相同的问题。我们拥有的插件是 Outlook 2003 的 VB6 COM 插件,它部署在数百台机器上,每天循环数百(如果不是数千)次。我们经历了很多加载和卸载循环。

在插件已加载但未连接的情况下,我们会遇到相当多的一般错误,我们会在代码中进行处理。(显然不是生产质量)

Dim outlook As outlook.Application
Set outlook = CreateObject("Outlook.Application")
outlook.COMAddIns("MyFancyDancyPlugin").Connect = True

很少,但不是那么罕见以至于它不是烦人,我们看到插件达到加载状态,我们可以在“工具>选项>其他>高级选项> Com加载项”中看到它,但是我们只是无法连接到这个东西。如果您尝试连接,则不会出现错误,它只是切换回断开连接。[相当于在注册表项中切换回 2] 据我所知,COM 对象从未创建过。该项目未列在已禁用项目中。

我们实际上不必重新部署来纠正这个错误。通过 Com Add-Ins 对话框删除对象,然后在此处重新添加它似乎可以解决问题。这仍然不是一个可接受的解决方案,但它确实可以在不重新安装的情况下恢复并运行。

  • Windows XP Professional,最新补丁级别
  • Outlook 2003 Professional,最新补丁级别
  • 不同版本的 McAfee Virus Scan(尽管禁用它没有效果 - 见上文)
  • 用户是本地管理员组的成员

这似乎很合适,我们不使用 McAfee,但病毒扫描程序也不与 Outlook 或 com 加载项交互。我们也不使用复制保护应用程序。

很抱歉,我无法提供更多帮助,但我很想从根本上解决这个问题。

于 2009-05-20T15:34:10.853 回答
2

我也在开发 Outlook 加载项,我知道加载项被禁用的一个原因。有时,当 Outlook 突然关闭或用户强行关闭 Outlook 时,加载项会被禁用。我不确定这是否是您的原因,但它也可以给您一些思考的方向。我有一段时间使用这种方法(在它仍在加载时使用任务管理器关闭 Outlook)来模拟这种行为,实际上我已经开发了一个工具来扫描提供给它的所有机器并检查加载项是否在机器上被禁用如果是,它会更改注册表值以启用它。

于 2009-02-27T13:56:00.473 回答
2

也许您是锁定政策的受害者。在注册表中添加一个旁路密钥,然后它就可以工作了。现代办公版本或 vsto 在安装时创建密钥。效果是:也安装一个现代办公室,现在插件也加载到旧办公室。请看一下

代码片段取自 NetOffice http://netoffice.codeplex.com

public static void RegisterFunction(Type type)
{
            try
            {
                // add codebase value
                Assembly thisAssembly = Assembly.GetAssembly(typeof(ExampleClassicAddin));
                RegistryKey key = Registry.ClassesRoot.CreateSubKey("CLSID\\{" + type.GUID.ToString().ToUpper() + "}\\InprocServer32\\1.0.0.0");
                key.SetValue("CodeBase", thisAssembly.CodeBase);
                key.Close();

                key = Registry.ClassesRoot.CreateSubKey("CLSID\\{" + type.GUID.ToString().ToUpper() + "}\\InprocServer32");
                key.SetValue("CodeBase", thisAssembly.CodeBase);
                key.Close();

                // add bypass key
                // http://support.microsoft.com/kb/948461
                key = Registry.ClassesRoot.CreateSubKey("Interface\\{000C0601-0000-0000-C000-000000000046}");
                string defaultValue = key.GetValue("") as string;
                if (null == defaultValue)
                    key.SetValue("", "Office .NET Framework Lockback Bypass Key");
                key.Close();

                // add addin key
                Registry.ClassesRoot.CreateSubKey(@"CLSID\{" + type.GUID.ToString().ToUpper() + @"}\Programmable");
                Registry.CurrentUser.CreateSubKey(_addinRegistryKey + _prodId);
                RegistryKey rk = Registry.CurrentUser.OpenSubKey(_addinRegistryKey + _prodId, true);
                rk.SetValue("LoadBehavior", Convert.ToInt32(3));
                rk.SetValue("FriendlyName", _addinName);
                rk.SetValue("Description", "NetOffice COMAddinExample with classic UI");
                rk.Close();
            }
            catch (Exception ex)
            {
                string details = string.Format("{1}{1}Details:{1}{1}{0}", ex.Message, Environment.NewLine);
                MessageBox.Show("An error occured." + details, "Register " + _addinName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
}
于 2011-05-31T02:35:13.340 回答
2

如果您有能力让您的用户在问题发生时运行调试程序以获取有关问题的更多信息,请尝试使用 Microsoft 的 Add-in Spy。

http://msdn.microsoft.com/en-us/library/cc984533(v=office.12).aspx

我有一个加载项无法加载并发现它正在发生,因为没有预加载依赖项。当 Outlook 加载项无法加载时,此工具应该能够告诉您发生了什么特定错误。

于 2011-08-16T18:35:34.297 回答
2

只是为了结束这一点:这个问题最终证明是由我们使用的第三方许可包装器中的错误引起的。它已得到供应商的确认,并在最近的版本中得到修复。

于 2012-02-03T10:24:58.013 回答