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
public static List<string> DirectoryList(string RootDirectory,
bool SearchAllDirectories, Predicate<string> Filter)
{
List<string> retList = new List<string>();
try
{
DirectoryInfo di = new DirectoryInfo(RootDirectory);
Parallel.ForEach(di.GetDirectories(), folder =>
{
try
{
if ((Filter == null) || (Filter(folder.FullName)))
{
retList.Add(folder.FullName);
if (SearchAllDirectories)
retList.AddRange(DirectoryList(folder.FullName, true,
Filter));
}
}
catch (UnauthorizedAccessException)
{
}
catch (Exception excep)
{
}
});
}
catch (Exception excep)
{
}
return retList;
}
#endregion
#region FileList
public static List<string> FileList(string RootDirectory,
bool SearchAllDirectories, Predicate<string> Filter)
{
List<string> retList = new List<string>();
try
{
List<string> DirList = new List<string> { RootDirectory };
if (SearchAllDirectories)
DirList.AddRange(DirectoryList(RootDirectory, true, null));
Parallel.ForEach(DirList, folder =>
{
DirectoryInfo di = new DirectoryInfo(folder);
try
{
foreach (FileInfo file in di.GetFiles())
{
try
{
if ((Filter == null) || (Filter(file.FullName)))
retList.Add(file.FullName);
}
catch (Exception excep)
{
}
}
}
catch (UnauthorizedAccessException)
{
}
catch (Exception excep)
{
}
});
}
catch (Exception excep)
{
}
return retList;
}
#endregion
}
}