如何在桌面Word已打开原文档时用Microsoft.Office.Interop.Word对比文档?
解决方案
核心问题分析
你新建的Word.Application是一个独立的Word进程,和桌面已打开的Word进程完全隔离,所以调用ActiveDocument会提示无文档打开。要实现需求,必须获取当前正在运行的Word应用实例,而非创建新实例。
具体实现步骤
- 用
Marshal.GetActiveObject获取已运行的Word进程实例 - 遍历已打开的文档集合,定位目标原文档
- 仅打开未在当前进程中打开的修订文档
- 执行文档对比逻辑
修改后的代码
using System; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Word; class WordComparer { public static void CompareDocuments(string originalPath, string revisedPath) { Application wordApp = null; Document doc1 = null; Document doc2 = null; Document comparisonDoc = null; try { // 获取已运行的Word应用实例,若没有则抛出异常 wordApp = (Application)Marshal.GetActiveObject("Word.Application"); // 从已打开的文档中查找原文档(通过完整路径匹配避免重名) foreach (Document doc in wordApp.Documents) { if (string.Equals(doc.FullName, originalPath, StringComparison.OrdinalIgnoreCase)) { doc1 = doc; break; } } if (doc1 == null) { throw new InvalidOperationException("原文档未在当前Word进程中打开"); } // 检查修订文档是否已打开,未打开则打开 foreach (Document doc in wordApp.Documents) { if (string.Equals(doc.FullName, revisedPath, StringComparison.OrdinalIgnoreCase)) { doc2 = doc; break; } } if (doc2 == null) { object missing = Type.Missing; object readOnly = false; doc2 = wordApp.Documents.Open( FileName: revisedPath, ReadOnly: readOnly, Visible: false // 修订文档后台打开 ); } // 执行文档对比 comparisonDoc = wordApp.CompareDocuments( doc1, doc2, WdCompareDestination.wdCompareDestinationNew, WdGranularity.wdGranularityWordLevel, CompareFormatting: true, CompareCaseChanges: true, CompareComments: true, CompareRevisions: true, CompareFields: true, CompareTables: true, CompareHeaders: true, CompareFootnotes: true, CompareTextboxes: true, CompareEquations: true, CompareObjects: true, ComparisonName: "", ShowSourceDocuments: WdShowSourceDocuments.wdShowSourceDocumentsNone ); // 可选:保存对比结果文档 // comparisonDoc.SaveAs2(@"C:\Path\To\ComparisonResult.docx"); } catch (COMException ex) { // 处理未找到Word进程的情况 Console.WriteLine("未检测到运行中的Word进程:" + ex.Message); } catch (Exception ex) { Console.WriteLine("对比失败:" + ex.Message); } finally { // 仅关闭代码中打开的修订文档,原文档保持打开状态 if (doc2 != null && string.Equals(doc2.FullName, revisedPath, StringComparison.OrdinalIgnoreCase) && !doc2.Saved) { doc2.Close(SaveChanges: WdSaveOptions.wdDoNotSaveChanges); } // 释放COM对象,避免内存泄漏 if (comparisonDoc != null) Marshal.ReleaseComObject(comparisonDoc); if (doc2 != null) Marshal.ReleaseComObject(doc2); if (doc1 != null) Marshal.ReleaseComObject(doc1); // 不要关闭wordApp,因为它是用户正在使用的进程 } } }
关键注意事项
- COM互操作权限:确保程序有足够权限访问Office COM组件,.NET Core项目需在Windows环境下运行(Office互操作仅支持Windows)
- 文档匹配逻辑:用
FullName而非Name匹配,避免同文件名不同路径的混淆 - 内存泄漏处理:必须手动释放COM对象,否则Word进程可能残留
- 异常处理:需处理未找到Word进程、原文档未打开等场景
内容的提问来源于stack exchange,提问作者yatin tripathi
相关产品推荐
相关产品推荐

