How to Get a List of Files and Folders Without Directory.GetFiles Access Denied Error
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.
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
}
}
loading...
loading...
No related posts.
Related posts brought to you by Yet Another Related Posts Plugin.
