MS Office Word VSTO“按需加载”

Posted

技术标签:

【中文标题】MS Office Word VSTO“按需加载”【英文标题】:MS Office Word VSTO “Load On Demand” 【发布时间】:2015-12-14 11:35:02 【问题描述】:

我们开发了一款标准 VSTO 插件产品(Word 2010 和 Word 2013,仅限 x86)。默认情况下,当它安装时,它会为所有用户安装(即,插件注册表项被插入到 HKLM - HKEY_LOCAL_MACHINE\SOFTWARE\[Wow6432Node]\Microsoft\Office\Word\Addins)。

LoadBehavior reg 键的值设置为0x3(即“启动时加载”)时,插件工作得非常好,但是当我们将LoadBehavior 的值设置为0x10(即“按需加载”),插件无法正常工作:

由于 UAC(并且 Word 没有运行提升),HKLM 中 LoadBehavior 的值不会从 0x10 更改为 0x9,而是通过创建 LoadBehavior 键(值为 @ 987654332@) 在 HKCU 蜂巢中。

不幸的是,我们发现这个 HKCU 被覆盖的值没有被考虑到除非清单键与 LoadBehavior) 一起存在于 HKCU 配置单元中。有关此相关线程的更多信息:https://social.msdn.microsoft.com/Forums/vstudio/en-US/3776734b-333e-423b-9c08-7c7a441c3e94/load-behavior-and-word-addin?forum=vsto

解决此问题的“明显”补救措施是在安装时将每个用户(以及 HKLM)的 Manifest 写入 HKCU 中,当每个用户第一次运行插件时.然而,这种方法有一些严重的缺点:

卸载插件需要删除每个用户的 HKCU 值,以防止用户遇到加载问题(不建议这样做,并且会带来其他问题/并发症,例如需要使用 Active Setup -Remove registry keys under HKCU on a per machine installation)。 在其(漫游)HKCU 配置单元中具有这些值的用户在登录到同一域中未安装我们插件的计算机时会遇到问题。

没有从 HKLM 获取清单是一个错误,在 HKCU 中正确设置了 LoadBehavior 吗?我认为如果 HKLM 中的 LoadBehavior 可以在 HKCU 中被覆盖而不需要 Manifest 值也被覆盖,那么这个问题将会得到解决。

有人知道解决这个问题的方法吗?

【问题讨论】:

【参考方案1】:

没有将 UAC 设置为“从不通知”,我不知道有什么方法可以直接解决您的问题。不过,我将建议一种解决方法,让您基本上按需加载

我建议您将 VSTO 插件的LoadBehavior 更改为 0x0(已卸载 - 不自动加载),然后在自动加载的模板中使用 VBA 命令来控制加载项的加载时间。以下是要采取的步骤的概要:

    在 Visual Studio 中,确保插件中的功能区被编码为 XML 文件(不是使用 Visual Designer 创建的)。在此功能区中定义自定义命名空间。 创建 Word 模板 (.dotm)。使用在此模板中嵌入的 Custom UI Editor for Microsoft Office 用于功能区选项卡的 XML,该功能区选项卡的标签和位置与加载项中的选项卡相同。将 XML 中的命名空间定义为与 Visual Studio XML 代码中的命名空间相同,以便它们共享相同的命名空间。此外,定义一个将加载您的插件的按钮(并且可能还可以在您的插件中执行其他功能)。

    在您的模板中编写一个子程序以使用此代码加载您已卸载的0x0 插件:

    Application.COMAddIns(ProgID).Connect = True

    ProgID 是您的 ProgID 的项目 ID,或者是引号中的 ProgID 的实际名称。

    在您的模板中编写一个回调,该回调将调用代码以从按钮加载插件。

    将模板放在 Word 的 STARTUP 目录中。对于 Word 2010,C:\Program Files (x86)\Microsoft Office\Office14\STARTUP

我们希望在启动 Word 时安装 VSTO 插件但未加载。您创建的模板会自动从 STARTUP 目录加载,并将您的应用程序的功能区选项卡放置在 Word 中。由于未加载 VSTO 插件,因此这些控件当前不可见。但是,在执行上述步骤后,当单击模板 XML 中的按钮时,您的插件会将其控件加载到同一功能区,因为它们共享一个命名空间。当 Word 关闭并重新启动时,它会重置为正在安装但未加载的 VSTO 插件。

更进一步,如果您想避免额外单击加载 VSTO 插件控件,您可以想象在模板中重新创建 VSTO 插件的 XML,并让每个控件调用代码来加载您的 VSTO 插件,隐藏模板的功能区控件,并执行插件的功能。这样,您的占位符功能区将由模板的 XML 和真正的插件加载并按需执行操作提供。

【讨论】:

【参考方案2】:

您使用 Load On Demand 的原因很可能是为了提高启动性能,如 MSDN 中所述。但是,按需加载会带来一系列问题(不支持动态功能区 UI 状态、HKLM 部署问题等)。

正如您已经说过的,在启动时加载没有问题。因此,加载加载项的推荐方法是使用 LoadBehavior0x3

如果您的加载项加载性能遇到问题,一种解决方案可能是使用轻量级加载项,该加载项始终在启动时加载,然后此加载项充当实际加载项的加载程序 -在。

【讨论】:

感谢@dirk-vollmar。澄清一下,想要使用 LoadOnDemand 的主要原因并不是因为我们的插件速度很慢,而是因为我们有很多非常多的插件,这些插件都是业务关键的。它们竞争资源,如果同时加载,通常会发生“冲突”和错误。唉,我们必须生活在一个我们无法更改其他加载项的世界中,而且当您拥有与我们大多数客户一样多的情况时,您不能要求他们都改善他们的负载。

以上是关于MS Office Word VSTO“按需加载”的主要内容,如果未能解决你的问题,请参考以下文章

Office(ExcelWord)二次开发——VSTO

为啥用VSTO代替VBA-VSTO 源码技巧区

深入理解vsto,开发word插件的利器

VSTO开发之一

在 VSTO for Word 中完全隐藏内容控制

如何在 VSTO Word 插件项目中设置自定义注册表?