J Bradley
J Bradley

Reputation: 109

Need to resume Try after Catch block

Coming from the VB6 era, I was able to use the "on error resume next" in a relatively appropriate manner when recursing through directories on my system. If my "foreach" loop encountered a Permission Denied or Access Denied error, all I had to do was call the "resume next" statement.

In C# however, this does not exist and I appreciate why. However, it boggles my mind to figure out how this is possible in C#.

I am trying to recurse through the directories on my hard drive and populate a TreeView control.

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);
        }

    }

The code is expected to work. However, the very moment it reaches the "C:\\Documents and Settings" folder on a Windows 7 machine, the catch block traps the "Access Denied" error (which I expect). What I would like to do is CONTINUE on with the next folder in series.

So the question is, how can I make this possible in C#?

My research shows a common opinion to use a TRY...CATCH block, but it doesn't show me how to do something so simple as what I am wanting to do above.

NOTE: I also try modifying the code to check the attributes as follows but it too fails.

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);
        }

    }

Upvotes: 4

Views: 21485

Answers (4)

Malcolm
Malcolm

Reputation: 1259

For this particular instance (the find files case), I have a work around that avoids the resume after exception problem (see below).

The problem is that GetFiles()/GetDirectories() or EnumerateFiles().GetEnumerator() forces evaluation of the Enumerable, and thus causes the exception to be thrown at that point.

see https://stackoverflow.com/a/9831340/89584 for a code example.

Upvotes: 0

BrokenGlass
BrokenGlass

Reputation: 160852

I think your method of choosing sub-directories is flawed, that's why you get the access exceptions - you have to exclude system directories, so something like this should work:

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

In your version using directory.GetDirectories("*", SearchOption.AllDirectories) you specifically ask for system directories to be included - SearchOption.AllDirectories will include system directories and reparse points. From MSDN:

The weakness in this approach is that if any one of the subdirectories under the specified root causes a DirectoryNotFoundException or UnauthorizedAccessException, the whole method fails and returns no directories. The same is true when you use the GetFiles method. If you have to handle these exceptions on specific subfolders, you must manually walk the directory tree, as shown in the following examples.

Upvotes: 4

msarchet
msarchet

Reputation: 15242

Instead of Try-Catching around the whole thing why not do it just where you need it to be.

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); } }

Upvotes: 0

Femaref
Femaref

Reputation: 61437

Move the try/catch block into the foreach loop, so you have the populating code in the try block. That way, you don't drop out of the loop when an exception is encountered.

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
  }
}

Upvotes: 7

Related Questions