Outlook VSTO插件:注册WindowSelectionChange事件致NormalEmail.dotm无法保存
解决Outlook VSTO插件注册WindowSelectionChange后NormalEmail.dotm无法保存的问题
这个问题的核心原因是你注册Word的WindowSelectionChange事件后,没有正确释放对Word Application对象的引用,导致Outlook关闭时无法正常终止内嵌的Word进程,进而无法完成NormalEmail.dotm的写入和保存操作——哪怕是空的事件处理方法,只要持有引用就会触发这个问题。
下面是具体的解决方案,结合代码示例说明:
关键修复步骤
- 为每个Inspector注册Close事件,在Inspector关闭时注销WindowSelectionChange事件并释放Word相关COM对象
- 从当前Inspector对应的Word编辑器获取Application实例,而不是通过ActiveExplorer全局获取,避免持有无效引用
- 使用
Marshal.ReleaseComObject手动释放COM对象,确保引用计数归零
修改后的完整代码示例
using System.Runtime.InteropServices; using Microsoft.Office.Interop.Outlook; using Microsoft.Office.Interop.Word; public partial class ThisAddIn { private void ThisAddIn_Startup(object sender, System.EventArgs e) { this.Application.Inspectors.NewInspector += Inspectors_NewInspector; } private void Inspectors_NewInspector(Outlook.Inspector inspector) { // 仅针对邮件类Inspector处理 if (inspector.CurrentItem is Outlook.MailItem) { // 绑定Inspector的Close事件,用于后续清理资源 ((InspectorEvents_Event)inspector).Close += () => { var wordEditor = inspector.WordEditor as Document; if (wordEditor != null) { var wordApp = wordEditor.Application; // 注销WindowSelectionChange事件 wordApp.WindowSelectionChange -= WinSelectionChange; // 手动释放COM对象引用,避免进程残留 Marshal.ReleaseComObject(wordApp); Marshal.ReleaseComObject(wordEditor); } }; // 获取当前Inspector对应的Word编辑器实例 var doc = inspector.WordEditor as Document; if (doc != null) { var wordApp = doc.Application; // 注册WindowSelectionChange事件 wordApp.WindowSelectionChange += WinSelectionChange; } } } private void WinSelectionChange(Selection Sel) { // 这里写你的事件处理逻辑 } private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { // 清理全局事件注册,避免残留引用 this.Application.Inspectors.NewInspector -= Inspectors_NewInspector; } }
额外注意事项
- 一定要避免直接持有
Application.ActiveExplorer().ActiveInlineResponseWordEditor的引用,这个对象会在会话中动态变化,且容易导致全局引用泄漏 - .NET垃圾回收器不会主动清理未释放的COM对象,手动释放是确保进程正常终止的关键
- 如果需要处理内嵌回复(Inline Response),可以额外监听
Explorer.InlineResponse事件,同样遵循「注册事件+注销事件+释放对象」的流程
这样修改后,Outlook关闭时就能正常终止Word进程,完成NormalEmail.dotm的保存操作,快速部件的修改会在重启后保留,删除该文件后Outlook也会正常重建新的模板文件。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

