来自VB6时代,当我通过系统上的目录递归时,我能够以相对适当的方式使用“on next error next”。如果我的“foreach”循环遇到Permission Denied或Access Denied错误,我所要做的就是调用“resume next”语句。
然而,在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);
}
}
预计代码可以正常运行。但是,当它到达Windows 7计算机上的"C:\\Documents and Settings"
文件夹时,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);
}
}
答案 0 :(得分:7)
将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
}
}
答案 1 :(得分:4)
我认为你选择子目录的方法是有缺陷的,这就是你获得访问异常的原因 - 你必须排除系统目录,所以这样的东西应该有效:
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:
这种方法的弱点在于 如果任何一个子目录下 指定的根导致a DirectoryNotFoundException或 UnauthorizedAccessException,整个 方法失败并返回否 目录。当你这样做时也是如此 使用GetFiles方法。如果你有 处理特定的这些例外 子文件夹,你必须手动走 目录树,如图所示 以下示例。
答案 2 :(得分:0)
而不是尝试捕捉整个事物,为什么不在你需要它的地方做它。
private void PopulateTree(string dir, TreeNode node)
{
// get the information of the directory
DirectoryInfo directory = new DirectoryInfo(dir);
// 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);
}
}
答案 3 :(得分:0)
对于这个特定的实例(查找文件的情况),我有一个解决方法,可以避免异常问题后的恢复(见下文)。
问题是GetFiles()/ GetDirectories()或EnumerateFiles()。GetEnumerator()强制评估Enumerable,从而导致异常被抛出。
请参阅https://stackoverflow.com/a/9831340/89584以获取代码示例。