Link to home
Start Free TrialLog in
Avatar of TeknikDev
TeknikDevFlag for United States of America

asked on

Searching for file in all folders using C#

Hi, I'm trying to search for files that are shortcuts in ALL directories including subfolders. I used this code but seems like it only searches one folder? I put C as the folder to search, but doesn't seem to go into every folder. Any help would be appreciated. Thanks in advance.

void DirSearch(string sDir)
        {
            try
            {
                foreach (string d in Directory.GetDirectories(sDir))
                {
                    foreach (string f in Directory.GetFiles(d, "*.lnk"))
                    {
                        lstFilesFound.Items.Add(f);
                    }
                    DirSearch(d);
                }
            }
            catch (System.Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
        }

Open in new window

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            DirSearch(@"C:\\");
        }

Open in new window

Avatar of Ivo Stoykov
Ivo Stoykov
Flag of Bulgaria image

This is shorter
string[] files = Directory.GetFiles(@"c:\files\folder1\", "*.*",SearchOption.AllDirectories);

Open in new window


Your source should be:
void DirSearch(string dir)
{
    try
    {
        foreach (string f in Directory.GetFiles(dir)) {  lstFilesFound.Items.Add(f);  }
        foreach (string d in Directory.GetDirectories(dir))
        {
//            lstFilesFound.Items.Add(d); // this will add directory name in the list
            DirSearch(d);
        }
    }
    catch (System.Exception e)
    {
        Console.WriteLine(e.Message);
    }
}

Open in new window

private void button3_Click(object sender, RoutedEventArgs e)
{
   DirSearch(@"C:\");
}

Open in new window

Avatar of Eduardo Goicovich
Better use

string[] files=Directory.GetFiles("C:\\",   "*.lnk",   SearchOption.AllDirectories)
Avatar of TeknikDev

ASKER

I don't see how you are using the shorter version of
string[] files 

Open in new window

I get "Access denied to Documents and Settings folder". Is there a way to bypass folders that I do not have access to? Also, how can I create a searching splash....? It takes a while to search and user may not know its doing anything.

                foreach (string f in Directory.GetFiles(dir, "*.lnk",  SearchOption.AllDirectories)) ;
                foreach (string d in Directory.GetDirectories(dir))
                {

Open in new window

Hi TeknikDev;

As stated in the C# Programming Guide the weakness in using GetDirectories and GetFiles is, "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.", they give two examples the first using recursion and the second walking the directory tree manually. Seeming you are looking to visit all directories do not use the recursion option as you will get a stack overflow. In walking the tree manually when trying to go into a directory you will need to catch the exception and try to elevate your permissions or just skip those directories. See the Microsoft documentation.

How to: Iterate Through a Directory Tree (C# Programming Guide)
Hey Fernando, can you provide the actual code on how to do this? Thanks
Hi TeknikDev;

The code is at the bottom of the link I posted above re-posted below. This code uses stack iteration as opposed to recursion.

public class StackBasedIteration
{
    static void Main(string[] args)
    {
        // Specify the starting folder on the command line, or in  
        // Visual Studio in the Project > Properties > Debug pane.
        TraverseTree(args[0]);

        Console.WriteLine("Press any key");
        Console.ReadKey();
    }

    public static void TraverseTree(string root)
    {
        // Data structure to hold names of subfolders to be 
        // examined for files.
        Stack<string> dirs = new Stack<string>(20);

        if (!System.IO.Directory.Exists(root))
        {
            throw new ArgumentException();
        }
        dirs.Push(root);

        while (dirs.Count > 0)
        {
            string currentDir = dirs.Pop();
            string[] subDirs;
            try
            {
                subDirs = System.IO.Directory.GetDirectories(currentDir);
            }
            // An UnauthorizedAccessException exception will be thrown if we do not have 
            // discovery permission on a folder or file. It may or may not be acceptable  
            // to ignore the exception and continue enumerating the remaining files and  
            // folders. It is also possible (but unlikely) that a DirectoryNotFound exception  
            // will be raised. This will happen if currentDir has been deleted by 
            // another application or thread after our call to Directory.Exists. The  
            // choice of which exceptions to catch depends entirely on the specific task  
            // you are intending to perform and also on how much you know with certainty  
            // about the systems on which this code will run. 
            catch (UnauthorizedAccessException e)
            {                    
                Console.WriteLine(e.Message);
                continue;
            }
            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }

            string[] files = null;
            try
            {
                files = System.IO.Directory.GetFiles(currentDir);
            }

            catch (UnauthorizedAccessException e)
            {

                Console.WriteLine(e.Message);
                continue;
            }

            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }
            // Perform the required action on each file here. 
            // Modify this block to perform your required task. 
            foreach (string file in files)
            {
                try
                {
                    // Perform whatever action is required in your scenario.
                    System.IO.FileInfo fi = new System.IO.FileInfo(file);
                    Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);
                }
                catch (System.IO.FileNotFoundException e)
                {
                    // If file was deleted by a separate application 
                    //  or thread since the call to TraverseTree() 
                    // then just continue.
                    Console.WriteLine(e.Message);
                    continue;
                }
            }

            // Push the subdirectories onto the stack for traversal. 
            // This could also be done before handing the files. 
            foreach (string str in subDirs)
                dirs.Push(str);
        }
    }
}

Open in new window

Thanks for this...but how can I re-write it so that it matches my original code? I'm very new to C#. Sorry but thank you for the assistance.

How will this work on a WPF form and executed by a click of  abutton.


I copied it freshly into a new project and then changed the debug starting object and set the working directory in Debug to C:\ (under Start Options) and get the error:

Index was outside the bounds of the array for TraverseTree(args[0]);
Hi TeknikDev;

The below code was modify to work with your setup. The only thing that is not there is getting elevated permissions. So currently it will get all files with *.lnk except for those that have access denied. As far as displaying it in a WPF view it all depends on how you have designed it and communicate with the view.

I used a List<string> for  lstFilesFound in the below code.
 
private void button3_Click(object sender, EventArgs e)
{
    DirSearch(@"C:\\");
    // Assign your lstFilesFound to a ListBox to see results
    listBox1.DataSource = lstFilesFound;
}

void DirSearch(string sDir)
{           

    // Data structure to hold names of subfolders to be 
    // examined for files.
    Stack<string> dirs = new Stack<string>(20);

    if (!System.IO.Directory.Exists(sDir))
    {
        throw new ArgumentException();
    }
    dirs.Push(sDir);

    while (dirs.Count > 0)
    {
        string currentDir = dirs.Pop();
        string[] subDirs = null;
        try
        {
            subDirs = System.IO.Directory.GetDirectories(currentDir);
        }
        // An UnauthorizedAccessException exception will be thrown if we do not have 
        // discovery permission on a folder or file. It may or may not be acceptable  
        // to ignore the exception and continue enumerating the remaining files and  
        // folders. It is also possible (but unlikely) that a DirectoryNotFound exception  
        // will be raised. This will happen if currentDir has been deleted by 
        // another application or thread after our call to Directory.Exists. The  
        // choice of which exceptions to catch depends entirely on the specific task  
        // you are intending to perform and also on how much you know with certainty  
        // about the systems on which this code will run. 
        catch (UnauthorizedAccessException e)
        {

            Console.WriteLine(e.Message);
            continue;
        }
        catch (System.IO.PathTooLongException e)
        {
            Console.WriteLine(e.Message + " : " + currentDir);
            continue;
        }
        catch (System.IO.DirectoryNotFoundException e)
        {
            Console.WriteLine(e.Message);
            continue;
        }

        string[] files = null;
        try
        {
            files = System.IO.Directory.GetFiles(currentDir, "*.lnk");
        }
        catch (System.IO.PathTooLongException e)
        {
            Console.WriteLine(e.Message + " : " + currentDir);
            continue;
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine(e.Message);
            continue;
        }
        catch (System.IO.DirectoryNotFoundException e)
        {
            Console.WriteLine(e.Message);
            continue;
        }
        // Perform the required action on each file here. 
        // Modify this block to perform your required task. 
        foreach (string file in files)
        {
            try
            {
                // Perform whatever action is required in your scenario.
                System.IO.FileInfo fi = new System.IO.FileInfo(file);
                lstFilesFound.Add(fi.FullName);
            }
            catch (System.IO.PathTooLongException e)
            {
                Console.WriteLine(e.Message + " : " + file);
                continue;
            }
            catch (System.IO.FileNotFoundException e)
            {
                // If file was deleted by a separate application 
                //  or thread since the call to TraverseTree() 
                // then just continue.
                Console.WriteLine(e.Message);
                continue;
            }
        }

        // Push the subdirectories onto the stack for traversal. 
        // This could also be done before handing the files. 
        foreach (string str in subDirs)
            dirs.Push(str);

    }
}

Open in new window

Ok ill give it a whirl, I'll replace the Console.Writeline with MessageBox.Show.
Ok  got this error message in the button click function:

listbox1.Datasource = lstFilesFound;

Error      1      'System.Windows.Controls.ListBox' does not contain a definition for 'DataSource' and no extension method 'DataSource' accepting a first argument of type 'System.Windows.Controls.ListBox' could be found (are you missing a using directive or an assembly reference?)      C:\visual studio 2010\Projects\WpfApplication2\WpfApplication2\MainWindow.xaml.cs      26      22      WpfApplication2


Error      2      The name 'lstFilesFound' does not exist in the current context      C:\visual studio 2010\Projects\WpfApplication2\WpfApplication2\MainWindow.xaml.cs      26      35      WpfApplication2
ASKER CERTIFIED SOLUTION
Avatar of Fernando Soto
Fernando Soto
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Im still getting errors  in Visual Studio 2010 for C# WPF

Error      1      The type or namespace name 'ObservableCollection' could not be found (are you missing a using directive or an assembly reference?)      C:\visual studio 2010\Projects\WpfApplication2\WpfApplication2\MainWindow.xaml.cs      31      58      WpfApplication2

 Error      2      Cannot implicitly convert type 'ObservableCollection<string>' to 'object'      c:\visual studio 2010\Projects\WpfApplication2\WpfApplication2\MainWindow.xaml.cs      27      32      WpfApplication2
When I created the test project the using statement for that library was included by default. If this using statement is missing add it to the list.

using System.Collections.ObjectModel
This worked! Thank you very much sir!
Not a problem, glad to help.