Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C++

How to Get a List of Files and Folders Without Directory.GetFiles Access Denied Error

Rate me:
Please Sign up or sign in to vote.
4.17/5 (4 votes)
20 Jul 2009CPOL 39.6K   19   10
I know the title is a bit long, but it descriptive of the problem. Recently I had need to retrieve a listing of files and folders given a root path. All worked well, until I tested on Vista and Windows 7 machines.

I know the title is a bit long, but it descriptive of the problem. Recently I had need to retrieve a listing of files and folders given a root path. All worked well, until I tested on Vista and Windows 7 machines. When trying to browse the "Users" folder, I kept getting access denied errors and no lists returned. The problem is that Directory.GetFiles and Directory.GetDirectories will fail on the first sign of an access denied issue. On Vista and Windows 7, most of the directories under the Users folder are ACL'd to not allow reading or browsing.

The solution is to use a DirectoryInfo object to get the list of directories, and loop through those. The solution I present below uses PLINQ (Parallel LINQ) for multi-threaded looping. If you do not have PLINQ installed, simply change the Parallel.ForEach statements to the standard ForEach.

Notice the use of a Predicate in both functions. This allows you to add advanced filtering, for example only returning files with an extension of ".jpg", or only returning files modified in the last five days.

C++
using System; 
using System.IO; 
using System.Threading; 
  
namespace MStaller 
{ 
    internal 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 List<string> DirectoryList(string RootDirectory,
            bool SearchAllDirectories, Predicate<string> Filter) 
        { 
            List<string> retList = new List<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 (UnauthorizedAccessException) 
                    { 
                        // don't really need to do anything 
                        // user just doesn't have access 
                    } 
  
                    catch (Exception excep) 
                    { 
                        // TODO: log the exception 
                    } 
                }); 
            } 
  
            catch (Exception excep) 
            { 
                // TODO: save exception 
            } 
  
            // 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 List<string> FileList(string RootDirectory,
            bool SearchAllDirectories, Predicate<string> Filter) 
        { 
            List<string> retList = new List<string>(); 
  
            try 
            { 
                // get the list of directories 
                List<string> DirList = new List<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 (Exception excep) 
                            { 
                                // TODO: log the exception 
                            } 
                        } 
                    } 
  
                    catch (UnauthorizedAccessException) 
                    { 
                        // don't really need to do anything 
                        // user just doesn't have access 
                    } 
  
                    catch (Exception excep) 
                    { 
                        // TODO: log the exception 
                    } 
                }); 
            } 
  
            catch (Exception excep) 
            { 
                // TODO: save exception 
            } 
  
            // return the list 
            return retList; 
        } 
  
        // FileList 
        #endregion 
    } 
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Winner - Best Mobile App - AT&T Developer Summit, Las Vegas, 2013

My personal resume can be found at: http://www.philippiercedeveloper.com

My game portfolio can be found at: http://www.rocketgamesmobile.com

About Philip Pierce:

I am a software developer with twenty years experience in game development, mobile, web, desktop, server, and database. My extensive background highlights an expertise in rapid application development using the latest Microsoft, Mobile, and Game Development technologies, along with the ability to create AI for games and business software, redesign existing software, develop multi-threaded software, and create client/server applications.

Comments and Discussions

 
Questioncreating the Predicate Pin
dave200712-Nov-12 15:25
dave200712-Nov-12 15:25 
GeneralBug in Windows 7 CFileDialog while working with filtering list of files and folders. Pin
ANIL KUMAR SHARMA (INDIA)21-Oct-09 18:07
ANIL KUMAR SHARMA (INDIA)21-Oct-09 18:07 
QuestionLink to PLINQ? Pin
STLMike16-Oct-09 8:55
STLMike16-Oct-09 8:55 
AnswerRe: Link to PLINQ? Pin
merlin98116-Oct-09 12:23
professionalmerlin98116-Oct-09 12:23 
GeneralInteresting but why PLINQ Pin
SurlyCanuck30-Jul-09 4:41
professionalSurlyCanuck30-Jul-09 4:41 
GeneralRe: Interesting but why PLINQ Pin
merlin98130-Jul-09 4:59
professionalmerlin98130-Jul-09 4:59 
GeneralRe: Interesting but why PLINQ Pin
SurlyCanuck30-Jul-09 5:02
professionalSurlyCanuck30-Jul-09 5:02 
Generalretlist Pin
jpmik20-Jul-09 11:12
jpmik20-Jul-09 11:12 
GeneralRe: retlist Pin
merlin98120-Jul-09 11:18
professionalmerlin98120-Jul-09 11:18 
Two things:

1) I originally used a list class I wrote that is thread safe and inherits all the List properties. Because that was class is not available for use in this demo, I changed it to use the Generic List.

2) For inserts only, which is what is happening here, retList will be fine. It is true, though, that for more complex actions (ie reading or deleting from the list during the loop), the list should be protected.

As I said before, the original object was a custom class I wrote, which provides all the protections necessary. A future article will go into detail how that list works.



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LINQ Exchange - Learn about LINQ and Lambda Expressions
Mentally Jumbled - Geek Blog

Joke of the Day and Random Jokes - ReallyFunnyQuickJokes.com
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GeneralRe: retlist Pin
Md. Marufuzzaman20-Jul-09 21:26
professionalMd. Marufuzzaman20-Jul-09 21:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.