UnauthorizedAccessException при получении файлов

Я создаю приложение, которое находит дублирование в файлах. Когда я ищу такие файлы, как:

try
{
    string[] allFiles = Directory.GetFiles(
        directoryPath, "*.*", SearchOption.AllDirectories
    );

    for (int i = 0; i < allFiles.Length; i++)
    {
      //decisions
    }
}

catch (UnauthorizedAccessException ex)
{
    MessageBox.Show(ex.Message);
}

это говорит

Доступ к пути 'C:\$Recycle.Bin.......' запрещен.

Я хочу, чтобы, если папка недоступна, перейти к следующей, но выполнение программы останавливается на методе Directory.GetFiles.


person Muhammad Ali Dildar    schedule 17.12.2011    source источник
comment
Назовем это особенностью, а не ошибкой. Ни один здравомыслящий пользователь не станет мириться с программой, которая становится зомби на минуты, пока она перебирает каждый файл на диске c:\. Терабайт — большое число.   -  person Hans Passant    schedule 18.12.2011
comment
@ Ганс, кто говорит, что приложение запускает пользовательский интерфейс при выполнении кода?   -  person sq33G    schedule 18.12.2011


Ответы (1)


Вот класс, который будет работать:

public static class FileDirectorySearcher
{
    public static IEnumerable<string> Search(string searchPath, string searchPattern)
    {
        IEnumerable<string> files = GetFileSystemEntries(searchPath, searchPattern);

        foreach (string file in files)
        {
            yield return file;
        }

        IEnumerable<string> directories = GetDirectories(searchPath);

        foreach (string directory in directories)
        {
            files = Search(directory, searchPattern);

            foreach (string file in files)
            {
                yield return file;
            }
        }
    }

    private static IEnumerable<string> GetDirectories(string directory)
    {
        IEnumerable<string> subDirectories = null;
        try
        {
            subDirectories = Directory.EnumerateDirectories(directory, "*.*", SearchOption.TopDirectoryOnly);
        }
        catch (UnauthorizedAccessException)
        {
        }

        if (subDirectories != null)
        {
            foreach (string subDirectory in subDirectories)
            {
                yield return subDirectory;
            }
        }
    }

    private static IEnumerable<string> GetFileSystemEntries(string directory, string searchPattern)
    {
        IEnumerable<string> files = null;
        try
        {
            files = Directory.EnumerateFileSystemEntries(directory, searchPattern, SearchOption.TopDirectoryOnly);
        }
        catch (UnauthorizedAccessException)
        {
        }

        if (files != null)
        {
            foreach (string file in files)
            {
                yield return file;
            }
        }
    }
}

Вы можете использовать его следующим образом:

IEnumerable<string> filesOrDirectories = FileDirectorySearcher.Search(@"C:\", "*.txt");

foreach (string fileOrDirectory in filesOrDirectories)
{
   // Do something here.
}

Это рекурсивно, но использование yield дает ему небольшой объем памяти (менее 10 КБ в моем тестировании). Если вам нужны только файлы, соответствующие шаблону, а не каталоги, просто замените EnumerateFileSystemEntries на EnumerateFiles.

person JamieSee    schedule 25.04.2012
comment
В этом коде есть серьезная ошибка... потому что EnumerateDirectories вернет IEnumerable, а затем, когда вы переберете IEnumerable, вы получите исключение UnauthorizedAccessException. Я обновил ваш код выше. - person Blake Niemyjski; 12.06.2012
comment
Привет @BlakeNiemyjski, я просматривал код, но не смог воспроизвести проблему, которую вы назвали своими адресами редактирования. Можете ли вы сказать мне конкретные шаги, чтобы воспроизвести его? - person JamieSee; 13.06.2012
comment
Ваш код собирал системные папки, такие как корзина. Я бы запустил ваш код от имени администратора и указал бы на ваш диск Windows. - person Blake Niemyjski; 16.07.2012
comment
@BlakeNiemyjski Я попробовал это на сервере Windows 2008 R2 в качестве администратора, на рабочей станции XP в качестве обычного пользователя и на рабочей станции XP в качестве администратора с FileDirectorySearcher.Search(@"C:\", "*.*");. Мне все еще не удалось воспроизвести неперехваченное исключение UnauthorizedAccessException. Как администратор он перечислил содержимое папки RECYCLER, а как обычный пользователь поймал исключение и продолжил работу. - person JamieSee; 01.08.2012
comment
Я видел эту проблему на Windows 7 x64. Я указал его как на мой диск C, так и на другие мои жесткие диски. Попробуйте включить отображение системных и скрытых папок в Проводнике. - person Blake Niemyjski; 08.08.2012
comment
Работает, но мне также пришлось поймать DirectoryNotFoundException при перечислении файловой системы WSL из Windows, обнаруженной при тестировании этого в моем домашнем каталоге. - person stijn; 16.04.2021
comment
Собственно, и PathTooLongException: документы .microsoft.com/en-us/dotnet/api/ - person stijn; 16.04.2021