Игнорировать папки/файлы, когда Directory.GetFiles() лишен доступа

Я пытаюсь отобразить список всех файлов, найденных в выбранном каталоге (и, возможно, любых подкаталогах). Проблема, с которой я сталкиваюсь, заключается в том, что когда метод GetFiles() попадает в папку, к которой он недоступен, он генерирует исключение и процесс останавливается.

Как игнорировать это исключение (и игнорировать защищенную папку/файл) и продолжать добавлять в список доступные файлы?

try
{
    if (cbSubFolders.Checked == false)
    {
        string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
        foreach (string fileName in files)
            ProcessFile(fileName);
    }
    else
    {
        string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories);
        foreach (string fileName in files)
            ProcessFile(fileName);
    }
    lblNumberOfFilesDisplay.Enabled = true;
}
catch (UnauthorizedAccessException) { }
finally {}

Ответ 1

Вам придется выполнять рекурсию вручную; не используйте AllDirectories - смотрите одну папку за раз, а затем попробуйте получить файлы из поддиректоров. Untested, но что-то вроде ниже (примечание использует делегат вместо построения массива):

using System;
using System.IO;
static class Program
{
    static void Main()
    {
        string path = ""; // TODO
        ApplyAllFiles(path, ProcessFile);
    }
    static void ProcessFile(string path) {/* ... */}
    static void ApplyAllFiles(string folder, Action<string> fileAction)
    {
        foreach (string file in Directory.GetFiles(folder))
        {
            fileAction(file);
        }
        foreach (string subDir in Directory.GetDirectories(folder))
        {
            try
            {
                ApplyAllFiles(subDir, fileAction);
            }
            catch
            {
                // swallow, log, whatever
            }
        }
    }
}

Ответ 2

Эта простая функция работает хорошо и отвечает требованиям к требованиям.

private List<string> GetFiles(string path, string pattern)
{
    var files = new List<string>();

    try 
    { 
        files.AddRange(Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly));
        foreach (var directory in Directory.GetDirectories(path))
            files.AddRange(GetFiles(directory, pattern));
    } 
    catch (UnauthorizedAccessException) { }

    return files;
}

Ответ 4

Простым способом сделать это является использование списка для файлов и очереди для каталогов. Он сохраняет память. Если вы используете рекурсивную программу для выполнения одной и той же задачи, это может вызвать исключение OutOfMemory. Вывод: файлы, добавленные в список, организованы в соответствии с деревом каталогов сверху вниз (шириной).

public static List<string> GetAllFilesFromFolder(string root, bool searchSubfolders) {
    Queue<string> folders = new Queue<string>();
    List<string> files = new List<string>();
    folders.Enqueue(root);
    while (folders.Count != 0) {
        string currentFolder = folders.Dequeue();
        try {
            string[] filesInCurrent = System.IO.Directory.GetFiles(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly);
            files.AddRange(filesInCurrent);
        }
        catch {
            // Do Nothing
        }
        try {
            if (searchSubfolders) {
                string[] foldersInCurrent = System.IO.Directory.GetDirectories(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly);
                foreach (string _current in foldersInCurrent) {
                    folders.Enqueue(_current);
                }
            }
        }
        catch {
            // Do Nothing
        }
    }
    return files;
}

Шаги:

  • Запуск корня в очереди
  • В цикле Dequeue it, добавьте файлы в этот каталог в список и добавьте подпапки в очередь.
  • Повторяйте, пока очередь не пуста.

Ответ 5

Это должно ответить на вопрос. Я проигнорировал проблему прохождения подкаталогов, я предполагаю, что вы это поняли.

Конечно, для этого вам не нужно иметь отдельный метод, но вы можете найти его полезным местом, чтобы проверить, что путь действителен, и иметь дело с другими исключениями, которые могут возникнуть при вызове GetFiles().

Надеюсь, что это поможет.

private string[] GetFiles(string path)
{
    string[] files = null;
    try
    {
       files = Directory.GetFiles(path);
    }
    catch (UnauthorizedAccessException)
    {
       // might be nice to log this, or something ...
    }

    return files;
}

private void Processor(string path, bool recursive)
{
    // leaving the recursive directory navigation out.
    string[] files = this.GetFiles(path);
    if (null != files)
    {
        foreach (string file in files)
        {
           this.Process(file);
        }
    }
    else
    {
       // again, might want to do something when you can't access the path?
    }
}

Ответ 6

Я знаю, что этот вопрос несколько старый, но сегодня у меня была такая же проблема, и я нашел следующую статью, в которой подробно описывается решение "рекурсия папки".

В статье признаются недостатки метода GetDirectories()...:

К сожалению, это [ с использованием метода GetDirectories()] имеет проблемы. Ключевым среди них является то, что некоторые из папки, которые вы пытаетесь прочитать, можно настроить так, чтобы текущий пользователь может не получить к ним доступ. Вместо того, чтобы игнорировать папки для который у вас ограниченный доступ, метод UnauthorizedAccessException. Однако мы можем обойти эту проблему путем создания собственного кода поиска рекурсивных папок.

... и затем подробно вносит решение:

http://www.blackwasp.co.uk/FolderRecursion.aspx

Ответ 7

см. fooobar.com/info/90618/... решение, которое обрабатывает проблему UnauthorizedAccessException.

Все вышеприведенные решения будут пропускать файлы и/или каталоги, если любые вызовы GetFiles() или GetDirectories() находятся в папках с сочетанием разрешений.