Previous Projects
Projects List

These are just a few of my more recent projects:
Florida Realty Insurint Health Benefits Direct Toezeeze
Rhabot Alliance Entertainment Homes.com
Code Samples
I also maintain the website LINQ Exchange, which teaches developers how to use LINQ and Lambda Expressions.
Contact

I can be reached at the follow:

email: philip@philippiercedeveloper.com

phone: 754-581-8362

Linked In: http://www.linkedin.com/in/philippierce

A recent project I worked on required me to retrieve a large listing of files and folders from a given computer. My original idea was to use the built in Directory.GetDirectories and Directory.GetFiles.

However, as I soon found out, there is a problem with both of these functions, especially when used in Windows Vista and Windows 7. These functions will error out (and return an empty array), if any of the folders/files are not accessible to the user. So, using Directory.GetDirectories(“C:\\”), would return an empty array and an exception, depending on the user’s security

The main problem comes from how some folders and files are ACL’d in Vista, and especially in Windows 7. Most users (including admin), cannot parse the path of some ACL’d folders, even if they have permission.

My solution was to create a class which can handle the security errors and still return all the files as needed. In addition, I wanted to make this as extensible as possible, so I also added a Predicate to each function, which allows you create your own filter.

example:
Get a list of all “jpg” files on the “C:” drive

TList<string> JpgFolders = DirectoryList(@"C:\\", true, x => (Path.GetExtension(x) == ".jpg"));

Because I use this heavily in multi-threaded environments, I have it returning the lists in a thread safe manner, using the thread safe List<> collection I wrote (TList).

Also, because of the number of files and folders being returned (sometimes in the hundreds of thousands or millions), I decided to use PLINQ to help speed things up. PLINQ allows me to branch each ForEach loop to a new thread, if a thread is available; otherwise, it will wait for an available thread. PLINQ can also send multiple iterations of the loop to one thread, which also helps to improve efficiency.

You’ll also notice the use multiple catch blocks. I found that two types of exceptions were raised if a user did not have access to a file/folder – IOException and UnauthorizedAccessException. There is no reason to do anything when these exceptions are raised, since it simply means the user does not have permission for this file/folder, so we just need to skip it.

The full class is below:

using System;

using System.IO;

using MerlinWebUtil.Error;

using Threaded;

using System.Threading;

 

namespace MerlinWebUtil.Utilities

{

    public static class DirectoryListing

    {

        #region DirectoryList

 

        /// <summary>

        /// Returns a list of directories under RootDirectory

        /// </summary>

        /// <param name="RootDirectory">starting directory</param>

        /// <param name="SearchAllDirectories">when true, all sub directories will be searched as well</param>

        /// <param name="Filter">filter to be done on directory. use null for no filtering</param>

        public static TList<string> DirectoryList(string RootDirectory, bool SearchAllDirectories, Predicate<string> Filter)

        {

            TList<string> retList = new TList<string>();

 

            try

            {

                // create a directory info object

                DirectoryInfo di = new DirectoryInfo(RootDirectory);

 

                // loop through directories populating the list

                Parallel.ForEach(di.GetDirectories(), folder =>

                    {

                        try

                        {

                            // add the folder if it passes the filter

                            if ((Filter == null) || (Filter(folder.FullName)))

                            {

                                // add the folder

                                retList.Add(folder.FullName);

 

                                // get it’s sub folders

                                if (SearchAllDirectories)

                                    retList.AddRange(DirectoryList(folder.FullName, true, Filter));

                            }

                        }

 

                        catch (IOException)

                        {

                            // don’t really need to do anything

                            // user just doesn’t have access

                        }

 

                        catch (UnauthorizedAccessException)

                        {

                            // don’t really need to do anything

                            // user just doesn’t have access

                        }

 

                        catch (Exception excep)

                        {

                            clsError.SaveException(excep);

                        }

                    });

            }

 

            catch (IOException)

            {

                // don’t really need to do anything

                // user just doesn’t have access

            }

 

            catch (UnauthorizedAccessException)

            {

                // don’t really need to do anything

                // user just doesn’t have access

            }

 

            catch (Exception excep)

            {

                clsError.SaveException(excep);

            }

 

            finally

            {

                // force garbage collection

                GC.Collect();

                Thread.Sleep(10);

            }

 

            // return the list

            return retList;

        }

 

        // DirectoryList

        #endregion

 

        #region FileList

 

        /// <summary>

        /// Returns a list of files under RootDirectory

        /// </summary>

        /// <param name="RootDirectory">starting directory</param>

        /// <param name="SearchAllDirectories">when true, all sub directories will be searched as well</param>

        /// <param name="Filter">filter to be done on files/directory. use null for no filtering</param>

        public static TList<string> FileList(string RootDirectory, bool SearchAllDirectories, Predicate<string> Filter)

        {

            TList<string> retList = new TList<string>();

 

            try

            {

                // get the list of directories

                TList<string> DirList = new TList<string> { RootDirectory };

 

                // get sub directories if allowed

                if (SearchAllDirectories)

                    DirList.AddRange(DirectoryList(RootDirectory, true, null));

 

                // loop through directories populating the list

                Parallel.ForEach(DirList, folder =>

                    {

                        // get a directory object

                        DirectoryInfo di = new DirectoryInfo(folder);

 

                        try

                        {

                            // loop through the files in this directory

                            foreach (FileInfo file in di.GetFiles())

                            {

                                try

                                {

                                    // add the file if it passes the filter

                                    if ((Filter == null) || (Filter(file.FullName)))

                                        retList.Add(file.FullName);

                                }

 

                                catch (IOException)

                                {

                                    // don’t really need to do anything

                                    // user just doesn’t have access

                                }

 

                                catch (UnauthorizedAccessException)

                                {

                                    // don’t really need to do anything

                                    // user just doesn’t have access

                                }

 

                                catch (Exception excep)

                                {

                                    clsError.SaveException(excep);

                                }

                            }

                        }

 

                        catch (IOException)

                        {

                            // don’t really need to do anything

                            // user just doesn’t have access

                        }

 

                        catch (UnauthorizedAccessException)

                        {

                            // don’t really need to do anything

                            // user just doesn’t have access

                        }

 

 

                        catch (Exception excep)

                        {

                            clsError.SaveException(excep);

                        }

                    });

            }

 

            catch (IOException)

            {

                // don’t really need to do anything

                // user just doesn’t have access

            }

 

            catch (UnauthorizedAccessException)

            {

                // don’t really need to do anything

                // user just doesn’t have access

            }

 

            catch (Exception excep)

            {

                clsError.SaveException(excep);

            }

 

            finally

            {

                // force garbage collection

                GC.Collect();

                Thread.Sleep(10);

            }

 

            // return the list

            return retList;

        }

 

        // FileList

        #endregion

    }

}

SocialTwist Tell-a-Friend