在启动时从本机COM加载Outlook VSTO加载项



我一直在为Outlook开发VSTO插件,在一些客户的pc上遇到了加载缓慢的问题(这显然是所有管理办公室插件的慢性病,因为CLR加载计入整个插件加载时间)。

我读过一个解决方案,有可能有VSTO插件加载通过设置其Connect属性为真从一个快速加载的原生COM插件:https://blogs.msdn.microsoft.com/andreww/2008/04/19/delay-loading-the-clr-in-office-add-ins/

我已经实现了它,但是即使在将VSTO外接程序的Connect属性从Native外接程序设置为true之后,它仍然没有加载。我有以下代码在OnStartupComplete执行:

CComVariant vtItem("VSTOAddInName");
Office::COMAddInsPtr spCOMAddins;
m_spOutlook->get_COMAddIns(&spCOMAddins);
if (spCOMAddins) {
    Office::COMAddInPtr spCOMAddIn;
    if (spCOMAddins->Item(&vtItem, &spCOMAddIn) == S_OK)
    {
        spCOMAddIn->put_Connect(VARIANT_TRUE);
        // I see this message!
        MessageBoxW(NULL, L"Connected flag set", L"Native_Addin", MB_OK);
    }
}
return S_OK;

m_spOutlook定义为:

Outlook::_ApplicationPtr m_spOutlook;

我看到了MessageBox,所以我假设设置了Connect属性,但是插件仍然没有加载。我试着用所有可能的LoadBehavior设置和没有这些工作。所以问题是这种变通方法是否有效?也许我应该在不同于OnStartupComplete的回调下执行它。对我来说,在outlook启动后几秒钟加载插件是很好的,我只需要加载它,而不是达到1秒启动限制。

我真的很感激你的帮助!

注:加载一次延迟加载的VSTO插件(LoadBehavior=16)对我来说只是一个部分解决方案,因为我需要功能区中的按钮在某些项目上被禁用,所以我需要插件真正加载。此外,有时按钮消失没有任何明显的原因,它需要最终用户做一些魔术把它找回来,这不是我的选择。

相反,我建议查看现有VSTO解决方案的源代码。将任何业务逻辑移到次要线程,以便Outlook能够尽可能快地加载插件。此外,您可以使用标准的。net机制来减少启动时间,例如:

  • 使用NGen.exe将代码生成从应用程序启动时移到安装时。
  • 利用GAC。如果未将程序集安装在全局程序集缓存(GAC)中,则会由于强命名程序集的散列验证和计算机上可用该程序集的本机映像时的Ngen映像验证而导致延迟。对于GAC中安装的所有程序集,将跳过强名称验证。有关更多信息,请参阅Gacutil.exe(全局程序集缓存工具)。
  • 延迟初始化操作。考虑将初始化代码推迟到呈现主应用程序窗口之后。请注意,初始化可以在类构造函数中执行,如果初始化代码引用了其他类,则可能导致执行许多类构造函数的级联效应。
  • Authenticode验证增加启动时间。必须使用证书颁发机构(CA)验证验证码签名的程序集。此验证可能非常耗时,因为它可能需要多次连接到网络以下载当前的证书撤销列表。它还确保在通往受信任根的路径上有完整的有效证书链。在加载程序集时,这可能会导致几秒钟的延迟。

您可以在应用程序启动时间文章中了解更多信息。

在Connect属性设置为true后,外接程序是否显示在禁用项列表中?

Microsoft Office应用程序可以禁用行为异常的VSTO插件。如果应用程序没有加载VSTO插件,则该应用程序可能已硬禁用或软禁用了VSTO插件。

当VSTO插件导致应用程序意外关闭时,可能会发生硬禁用。如果在VSTO外接程序中的启动事件处理程序执行时停止调试器,也可能发生在开发计算机上。

当VSTO外接程序产生一个不会导致应用程序意外关闭的错误时,可能会发生软禁用。例如,如果在Startup事件处理程序执行时抛出未处理的异常,应用程序可能会软禁用VSTO外接程序。

当您重新启用软禁用的VSTO插件时,应用程序会立即尝试加载VSTO插件。如果最初导致应用程序软禁用VSTO外接程序的问题尚未解决,则应用程序将再次软禁用VSTO外接程序。在如何:重新启用已禁用的VSTO加载项文章中了解更多信息。

您是否尝试手动启用加载项?你会得到相同的结果吗?

最新更新