Необходимо возобновить попытку после блокирования Catch

Появившись в эпоху VB6, я смог использовать "возобновление при следующей ошибке" относительно подходящим образом при повторном просмотре каталогов в моей системе. Если мой цикл "foreach" обнаружил ошибку "Отказано в доступе" или "Отказано в доступе", все, что мне нужно было сделать, это вызвать оператор "возобновить следующее".

Однако в C# этого не существует, и я понимаю, почему. Тем не менее, я не могу понять, как это возможно в C#.

Я пытаюсь просмотреть каталоги на жестком диске и заполнить элемент управления TreeView.

private void PopulateTree(string dir, TreeNode node)
    {
        try
        {
            // get the information of the directory
            DirectoryInfo directory = new DirectoryInfo(dir);

            // loop through each subdirectory
            foreach (DirectoryInfo d in directory.GetDirectories("*", SearchOption.AllDirectories))
            {
                // create a new node
                TreeNode t = new TreeNode(d.Name);
                // populate the new node recursively
                PopulateTree(d.FullName, t);
                node.Nodes.Add(t); // add the node to the "master" node
            }

            // lastly, loop through each file in the directory, and add these as nodes
            foreach (FileInfo f in directory.GetFiles())
            {
                // create a new node
                TreeNode t = new TreeNode(f.Name);
                // add it to the "master"
                node.Nodes.Add(t);
            }
        }
        catch (System.Exception e)
        {
            MessageBox.Show(e.Message, "Error Loading Directories", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

    }

Ожидается, что код будет работать. Однако в тот самый момент, когда он достигает "C:\\Documents and Settings" В папке на компьютере с Windows 7 блок catch перехватывает ошибку "Отказано в доступе" (что я ожидаю). То, что я хотел бы сделать, это ПРОДОЛЖИТЬ со следующей папкой в ​​серии.

Итак, вопрос в том, как я могу сделать это возможным в C#?

Мое исследование показывает общее мнение об использовании блока TRY...CATCH, но оно не показывает мне, как сделать что-то настолько простое, как то, что я хочу сделать выше.

ПРИМЕЧАНИЕ: я также пытаюсь изменить код, чтобы проверить атрибуты следующим образом, но он тоже не работает.

private void PopulateTree(string dir, TreeNode node)
    {
        try
        {
            // get the information of the directory
            DirectoryInfo directory = new DirectoryInfo(dir);

            if (directory.Attributes == FileAttributes.ReparsePoint || directory.Attributes == FileAttributes.System)
            {
                Console.Write("Access denied to folder.");
            }
            else
            {

                // loop through each subdirectory
                foreach (DirectoryInfo d in directory.GetDirectories("*", SearchOption.AllDirectories))
                {
                    // create a new node
                    TreeNode t = new TreeNode(d.Name);
                    // populate the new node recursively
                    PopulateTree(d.FullName, t);
                    node.Nodes.Add(t); // add the node to the "master" node
                }

                // lastly, loop through each file in the directory, and add these as nodes
                foreach (FileInfo f in directory.GetFiles())
                {
                    // create a new node
                    TreeNode t = new TreeNode(f.Name);
                    // add it to the "master"
                    node.Nodes.Add(t);
                }
            }
        }
        catch (System.Exception e)
        {
            MessageBox.Show(e.Message, "Error Loading Directories", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

    }

4 ответа

Переместите блок try/catch в цикл foreach, чтобы у вас был заполненный код в блоке try. Таким образом, вы не выпадает из цикла при возникновении исключения.

foreach(var item in col)
{
  try
  {
     //do stuff with item
  }
  catch 
  {
     //yes, this is empty, but in this case it is okay as there is no other way
  }
}

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

var subDirectories = directory.GetDirectories()
                              .Where(d => (d.Attributes & FileAttributes.ReparsePoint) ==0  
                                     && (d.Attributes & FileAttributes.System) == 0);
foreach (DirectoryInfo d in subDirectories)
{
  //...
}   

В вашей версии используя directory.GetDirectories("*", SearchOption.AllDirectories) Вы специально просите включить системные каталоги - SearchOption.AllDirectories будет включать системные каталоги и точки повторного анализа. Из MSDN:

Недостатком этого подхода является то, что если какой-либо из подкаталогов в указанном корне вызывает исключение DirectoryNotFoundException или UnauthorizedAccessException, весь метод завершается ошибкой и не возвращает никаких каталогов. То же самое верно, когда вы используете метод GetFiles. Если вам нужно обработать эти исключения в определенных подпапках, вы должны вручную пройтись по дереву каталогов, как показано в следующих примерах.

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

Проблема заключается в том, что GetFiles () / GetDirectories () или EnumerateFiles (). GetEnumerator () форсирует оценку Enumerable и, таким образом, вызывает исключение в этой точке.

см. /questions/6708839/unauthorizedaccessexception-ne-mozhet-razreshit-oshibku-directorygetfiles/6708864#6708864 для примера кода.

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

 private void PopulateTree (строка dir, узел TreeNode)
    {
        // получить информацию о каталоге
        DirectoryInfo directory = new DirectoryInfo(каталог);

// loop through each subdirectory foreach (DirectoryInfo d in directory.GetDirectories("*", SearchOption.AllDirectories)) { try { // create a new node TreeNode t = new TreeNode(d.Name); // populate the new node recursively PopulateTree(d.FullName, t); node.Nodes.Add(t); // add the node to the "master" node } catch (System.Exception e) { MessageBox.Show(e.Message, "Error Loading Directories", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } // lastly, loop through each file in the directory, and add these as nodes foreach (FileInfo f in directory.GetFiles()) { // create a new node TreeNode t = new TreeNode(f.Name); // add it to the "master" node.Nodes.Add(t); } }
Другие вопросы по тегам