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

如何调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:05:29