Directory.EnumerateFiles 是否会锁定它正在尝试复制的文件?

3
我正在尝试编写一个程序将我的SQL数据库备份文件复制到NAS。它之前是可以运行的,但是我添加了检查路径是否存在的功能后,当它尝试复制文件时,会出现异常,显示“System.IO.IOException:由于另一个进程正在使用,无法访问文件'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\AdventureWorks2012.bak'。”。
我已经使用过进程资源管理器检查过了,没有其他程序正在操作该文件。
我做错了什么?
下面是代码:
namespace BackupCopy
{
    class Program
    {
        static void Main(string[] args)
        {
            // Set Source Path
            string sourcePath = @"C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup";

            // Verify Source Path Exists
            if (!Directory.Exists(sourcePath))
            {
                Console.WriteLine("Source path does not exist.");
                Console.ReadLine();
                return;
            }



            // Backup each file in Array
            foreach (string filename in Directory.EnumerateFiles(sourcePath))
            {
                Backup(filename);
            }

        }

        public static void Backup(string filename)
        {
            // Pull filename from method input parameter
            string fileName = filename;

            // Set Paths
            string sourcePath = @"C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup";
            string targetPath = @"\\prometheus\NAS\DB Backups\mercurys";

            // Verify Target Path Exists
            if (!Directory.Exists(targetPath))
            {
                Console.WriteLine("Target path does not exist.");
                Console.ReadLine();
                return;
            }

            // Use Path class to manipulate file and directory paths. 
            string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
            string destFile = System.IO.Path.Combine(targetPath, fileName);

            // To copy a file to another location and  
            // overwrite the destination file if it already exists.
            try
            {
                System.IO.File.Copy(sourceFile, destFile, true);
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc);
                Console.ReadLine();
                return;
            }
        }
    }
}

2
给定路径上已经有另一个进程在运行。对我来说,Winternals的Process Explorer从未失败过,可以找到给定文件路径下的打开文件句柄 - 尽管有可能该文件是通过(不同的路径)映射访问的。 - user2864740
请再次阅读问题,我已经在使用“进程资源管理器”进行检查。 - CryptoJones
1
再次阅读注释。我委婉地表示“我怀疑PE的正确用法”。无论如何,与openfiles(Windows命令)和handle(Winternals套件的一部分)协作查找。尽可能少限制搜索。 - user2864740
通过删除Directory.Enumerate Files foreach并将文件名硬编码,我确认这是我的程序。 - CryptoJones
1
我认为问题可能是Directory.EnumerateFiles()锁定了_directory_,当目录被锁定时,目标文件的目录条目无法更新。您可以通过使用Directory.GetFiles()获取所有文件的列表,然后遍历文件名数组,而不是使用Directory.EnumerateFiles()。 - RenniePet
太棒了。谢谢RenniePet! - CryptoJones
1个回答

1
问题在于程序在枚举目录中的文件时锁定了文件句柄。
将其替换为:
        // Backup each file in Array
        foreach (string filename in Directory.EnumerateFiles(sourcePath))
        {
            Backup(filename);
        }

使用此代码;
        Backup("AdventureWorks2012.bak");

解决问题。

2
或者将 EnumerateFiles(它持有一个锁,以便按顺序读取每个文件)替换为 GetFiles(它在开始时检索完整列表并不锁定目录——唯一的缺点是在大型文件夹上的性能,但这似乎不是您的情况)。 - fyjham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接