You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.20 16:15:49