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