Блокирует ли Directory.EnumerateFiles файл, который пытается скопировать?

Я пытаюсь написать программу для копирования файлов резервной копии базы данных 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;
            }
        }
    }
}

person CryptoJones    schedule 29.03.2015    source источник
comment
Есть другой процесс с открытым заданным путем. Для меня Process Explorer Winternals всегда находил открытый файл обрабатывает заданный путь к файлу - хотя возможно, что доступ к файлу осуществляется через сопоставление (другой путь).   -  person user2864740    schedule 30.03.2015
comment
Прочитайте вопрос еще раз, я уже использую Process Explorer для проверки.   -  person CryptoJones    schedule 30.03.2015
comment
Прочтите комментарий еще раз. Я говорю, что сомневаюсь в правильном использовании PE. В любом случае, сотрудничайте с выводами с помощью openfiles (команда Windows) и handle (часть пакета Winternals). Сделайте поиск как можно менее ограничительным.   -  person user2864740    schedule 30.03.2015
comment
Я подтвердил, что это была моя программа, вынув Directory.Enumerate Files foreach и жестко закодировав имя файла.   -  person CryptoJones    schedule 30.03.2015
comment
Я думаю, возможно, проблема в том, что Directory.EnumerateFiles() блокирует каталог, и когда каталог заблокирован, запись каталога для целевого файла не может быть обновлена. Вместо использования Directory.EnumerateFiles() вы можете получить список всех файлов через Directory.GetFiles(), а затем просмотреть массив имен файлов.   -  person RenniePet    schedule 30.03.2015
comment
Потрясающий. Спасибо РенниПет!   -  person CryptoJones    schedule 30.03.2015


Ответы (1)


Проблема в том, что программа блокирует дескриптор файла при перечислении файла в каталоге.

Замена этого;

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

С этим;

        Backup("AdventureWorks2012.bak");

Решает проблему.

person CryptoJones    schedule 30.03.2015
comment
В качестве альтернативы замените EnumerateFiles (который удерживает блокировку, чтобы он мог читать каждый файл последовательно) на GetFiles (который извлекает полный список в начале и не блокирует каталог - единственным недостатком которого является производительность на больших папках, но это не похоже, это ваш сценарий). - person fyjham; 30.03.2015