C# WPF中递归遍历文件夹批量将Word文档转换为XPS
递归批量转换多层目录下Word文档为XPS实现方案
你已经完成了单文件转换的基础逻辑,要实现嵌套文件夹的批量转换,只需要补充目录递归遍历逻辑,同时优化现有单文件转换逻辑的资源泄漏问题即可。
现有单文件逻辑的问题
你当前写的convertWordToXps方法存在几个影响批量转换稳定性的问题:
- 每转换一个文件就新建、退出一次Word进程,转换大量文件时速度极慢,还容易产生大量残留的WINWORD后台进程
- 直接通过
ActiveDocument获取文档对象,批量操作时容易出现对象引用错误 - 直接用字符串拼接路径,容易出现多余斜杠的路径格式错误
- 没有显式释放COM对象,很容易造成内存泄漏
完整实现代码
下面的实现包含递归目录遍历、优化后的单文件转换逻辑、资源释放和异常兼容:
using System; using System.IO; using System.Collections.Generic; using Word = Microsoft.Office.Interop.Word; using System.Windows.Forms; public static class WordXpsBatchConverter { private static Word.Application _wordInstance; // 支持转换的Word格式后缀 private static readonly HashSet<string> SupportedWordExts = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".doc", ".docx", ".docm", ".rtf", ".dot", ".dotx" }; /// <summary> /// 批量转换入口,传入根目录路径即可递归转换所有子目录下的Word文件 /// </summary> /// <param name="rootFolder">Instructions主文件夹的完整路径</param> public static void RunBatchConvert(string rootFolder) { if (!Directory.Exists(rootFolder)) { MessageBox.Show("指定的根目录不存在,请检查路径"); return; } // 全局只初始化一次Word进程,所有文件复用 _wordInstance = new Word.Application { Visible = false, DisplayAlerts = Word.WdAlertLevel.wdAlertsNone }; try { TraverseAndConvert(rootFolder); MessageBox.Show("全部文档转换完成"); } catch (Exception ex) { MessageBox.Show($"转换流程异常中断:{ex.Message}"); } finally { // 所有转换完成后统一释放Word进程 if (_wordInstance != null) { _wordInstance.Quit(SaveChanges: false); System.Runtime.InteropServices.Marshal.ReleaseComObject(_wordInstance); _wordInstance = null; GC.Collect(); GC.WaitForPendingFinalizers(); } } } /// <summary> /// 递归遍历目录,处理所有Word文件和子目录 /// </summary> private static void TraverseAndConvert(string currentDir) { // 处理当前目录下所有支持格式的Word文件 foreach (var filePath in Directory.GetFiles(currentDir)) { var fileExt = Path.GetExtension(filePath); if (SupportedWordExts.Contains(fileExt)) { ConvertSingleFile(filePath); } } // 递归遍历子目录 foreach (var subDirPath in Directory.GetDirectories(currentDir)) { var dirInfo = new DirectoryInfo(subDirPath); // 跳过系统、隐藏目录,避免访问无权限目录抛错 if ((dirInfo.Attributes & FileAttributes.Hidden) != 0 || (dirInfo.Attributes & FileAttributes.System) != 0) continue; try { TraverseAndConvert(subDirPath); } catch (UnauthorizedAccessException) { // 无权限访问的目录直接跳过,不中断整体转换流程 continue; } } } /// <summary> /// 单个Word文件转XPS逻辑 /// </summary> private static string ConvertSingleFile(string wordFilePath) { Word.Document currentDoc = null; string xpsSavePath = Path.Combine( Path.GetDirectoryName(wordFilePath), Path.GetFileNameWithoutExtension(wordFilePath) + ".xps" ); // 已存在同名XPS文件则直接跳过,避免重复转换 if (File.Exists(xpsSavePath)) return xpsSavePath; try { currentDoc = _wordInstance.Documents.Open( FileName: wordFilePath, ConfirmConversions: false, ReadOnly: true, Visible: false ); currentDoc.SaveAs2(FileName: xpsSavePath, FileFormat: Word.WdSaveFormat.wdFormatXPS); return xpsSavePath; } catch (Exception ex) { MessageBox.Show($"文件【{wordFilePath}】转换失败:{ex.Message}"); return null; } finally { // 关闭当前文档,释放COM对象 if (currentDoc != null) { currentDoc.Close(SaveChanges: false); System.Runtime.InteropServices.Marshal.ReleaseComObject(currentDoc); currentDoc = null; } } } }
调用方法
在你的业务代码中直接调用入口方法,传入Instructions文件夹的实际路径即可:
// 替换为你本地Instructions文件夹的实际路径 string rootPath = @"D:\Files\Instructions"; WordXpsBatchConverter.RunBatchConvert(rootPath);
注意事项
- 运行程序的设备必须安装Microsoft Office Word,Interop转换逻辑依赖本地安装的Word组件
- 不要在多线程环境下调用转换逻辑,Office COM组件不支持并发调用,容易出现随机异常
- 如果待转换文件总量超过1000个,可以在逻辑中加入计数,每转换200个文件重启一次Word实例,避免长时间运行出现内存泄漏
- 转换生成的XPS文件和原Word文件保存在同目录下,文件名保持一致
内容的提问来源于stack exchange,提问作者Muhammad zubair
相关产品推荐
相关产品推荐

