如何调用Windows原生多文件复制/移动对话框实现批量文件操作?
实现批量文件复制/移动并显示Windows原生统一进度对话框
要实现批量复制/移动文件时显示系统原生的统一进度对话框(而非单个文件单独弹窗),可以直接调用Windows Shell提供的原生API,以下是两种可行方案:
方案1:使用SHFileOperation(兼容全版本Windows)
这是传统的Shell操作接口,支持批量文件操作,能弹出和系统自带复制一致的进度对话框。
代码实现
using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private struct SHFILEOPSTRUCT { public IntPtr hwnd; public uint wFunc; [MarshalAs(UnmanagedType.LPTStr)] public string pFrom; [MarshalAs(UnmanagedType.LPTStr)] public string pTo; public ushort fFlags; public bool fAnyOperationsAborted; public IntPtr hNameMappings; [MarshalAs(UnmanagedType.LPTStr)] public string lpszProgressTitle; } public class BatchFileOperations { [DllImport("shell32.dll", CharSet = CharSet.Auto)] private static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp); // 操作类型常量 private const uint FO_COPY = 0x0002; private const uint FO_MOVE = 0x0001; // 对话框控制常量 private const ushort FOF_SIMPLEPROGRESS = 0x0004; // 显示统一进度对话框 private const ushort FOF_ALLOWUNDO = 0x0040; // 允许撤销操作 private const ushort FOF_NOCONFIRMMKDIR = 0x0200; // 自动创建目标目录无需确认 private const ushort FOF_NOCONFIRMATION = 0x0010; // 覆盖文件无需确认(可选) /// <summary> /// 批量复制文件 /// </summary> /// <param name="sourceFiles">源文件路径数组</param> /// <param name="targetDir">目标目录</param> /// <returns>操作结果,0表示成功</returns> public static int CopyFiles(string[] sourceFiles, string targetDir) { var fileOp = new SHFILEOPSTRUCT { wFunc = FO_COPY, // 源文件用\0分隔,结尾必须加两个\0 pFrom = string.Join("\0", sourceFiles) + "\0\0", // 目标目录结尾加一个\0 pTo = targetDir + "\0", fFlags = FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR, lpszProgressTitle = "批量复制文件" // 进度框标题 }; // 若需要覆盖确认,移除下面的注释并删除FOF_NOCONFIRMATION // fileOp.fFlags |= FOF_NOCONFIRMATION; return SHFileOperation(ref fileOp); } /// <summary> /// 批量移动文件 /// </summary> /// <param name="sourceFiles">源文件路径数组</param> /// <param name="targetDir">目标目录</param> /// <returns>操作结果,0表示成功</returns> public static int MoveFiles(string[] sourceFiles, string targetDir) { var fileOp = new SHFILEOPSTRUCT { wFunc = FO_MOVE, pFrom = string.Join("\0", sourceFiles) + "\0\0", pTo = targetDir + "\0", fFlags = FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR, lpszProgressTitle = "批量移动文件" }; return SHFileOperation(ref fileOp); } } // 使用示例 // string[] sourcePaths = { @"C:\Documents\1.txt", @"C:\Documents\3.txt" }; // string targetDirectory = @"D:\Backup"; // BatchFileOperations.CopyFiles(sourcePaths, targetDirectory);
方案2:使用IFileOperation(推荐,适配现代Windows)
这是Windows Vista及以上系统提供的更现代化的Shell接口,功能更丰富,同样支持原生进度对话框。
代码实现
需要先添加COM引用:右键项目 → 添加 → 引用 → COM → 选择「Microsoft Shell Controls And Automation (版本1.0)」
using Shell32; using System.Collections.Generic; using System.IO; public static class ModernBatchFileOps { /// <summary> /// 批量复制文件 /// </summary> /// <param name="sourcePaths">源文件路径列表</param> /// <param name="targetDir">目标目录</param> public static void CopyFiles(List<string> sourcePaths, string targetDir) { var shell = new Shell(); var targetFolder = shell.NameSpace(targetDir); foreach (var sourcePath in sourcePaths) { var sourceDir = Path.GetDirectoryName(sourcePath); var sourceFileName = Path.GetFileName(sourcePath); var sourceItem = shell.NameSpace(sourceDir).ParseName(sourceFileName); // CopyHere参数:0x0004=显示进度框,0x0010=允许撤销,0x0400=覆盖无需确认(可选) targetFolder.CopyHere(sourceItem, 0x0004 | 0x0010); } } /// <summary> /// 批量移动文件 /// </summary> /// <param name="sourcePaths">源文件路径列表</param> /// <param name="targetDir">目标目录</param> public static void MoveFiles(List<string> sourcePaths, string targetDir) { var shell = new Shell(); var targetFolder = shell.NameSpace(targetDir); foreach (var sourcePath in sourcePaths) { var sourceDir = Path.GetDirectoryName(sourcePath); var sourceFileName = Path.GetFileName(sourcePath); var sourceItem = shell.NameSpace(sourceDir).ParseName(sourceFileName); targetFolder.MoveHere(sourceItem, 0x0004 | 0x0010); } } } // 使用示例 // var sources = new List<string> { @"C:\1.txt", @"C:\3.txt" }; // ModernBatchFileOps.CopyFiles(sources, @"D:\Target");
方案优势
这两种方案均调用Windows原生Shell功能,弹出的对话框与系统自带的复制/移动对话框完全一致,支持:
- 统一的进度展示(不会为单个文件单独弹窗)
- 文件覆盖确认、自动创建目录等交互
- 撤销操作支持
- 系统级的错误处理
这也是TeamViewer、AnyDesk等软件实现该功能的底层方式。
内容的提问来源于stack exchange,提问作者Gray Programmerz
相关产品推荐
相关产品推荐

