Ignore Folders/Files When Directory.Getfiles() Is Denied Access

Ignore folders/files when Directory.GetFiles() is denied access

You will have to do the recursion manually; don't use AllDirectories - look one folder at a time, then try getting the files from sub-dirs. Untested, but something like below (note uses a delegate rather than building an array):

using System;
using System.IO;
static class Program
{
static void Main()
{
string path = ""; // TODO
ApplyAllFiles(path, ProcessFile);
}
static void ProcessFile(string path) {/* ... */}
static void ApplyAllFiles(string folder, Action<string> fileAction)
{
foreach (string file in Directory.GetFiles(folder))
{
fileAction(file);
}
foreach (string subDir in Directory.GetDirectories(folder))
{
try
{
ApplyAllFiles(subDir, fileAction);
}
catch
{
// swallow, log, whatever
}
}
}
}

Access to the path is denied when using Directory.GetFiles(...)

If you want to continue with the next folder after a fail, then yea; you'll have to do it yourself. I would recommend a Stack<T> (depth first) or Queue<T> (bredth first) rather than recursion, and an iterator block (yield return); then you avoid both stack-overflow and memory usage issues.

Example:

    public static IEnumerable<string> GetFiles(string root, string searchPattern)
{
Stack<string> pending = new Stack<string>();
pending.Push(root);
while (pending.Count != 0)
{
var path = pending.Pop();
string[] next = null;
try
{
next = Directory.GetFiles(path, searchPattern);
}
catch { }
if(next != null && next.Length != 0)
foreach (var file in next) yield return file;
try
{
next = Directory.GetDirectories(path);
foreach (var subdir in next) pending.Push(subdir);
}
catch { }
}
}

How can i ignore access denied when searching to get all sub directories?

Your problem might be that you don't visit (add to the list) the current directory before recursively visiting its subdirectories. So if you get an exception there, nothing will be added to the list.

The following works for me. (I've also made it a bit more generic by using callbacks and made the exception handling stricter.)

class DirectoryHelper
{
public static void Test()
{
DirectoryHelper.EnumerateSubDirectories(@"c:\windows\system32");
}

public static List<string> EnumerateSubDirectories(string path)
{
// Depending on your use case, it might be
// unecessary to save these in memory
List<string> allSubdirs = new List<string>();
EnumerateSubDirectories(path,
filePath => Console.WriteLine("Visited file: " + filePath),
dirPath => allSubdirs.Add(dirPath),
noAccessPath => Console.WriteLine("No access: " + noAccessPath)
);
return allSubdirs;
}

private static void EnumerateSubDirectories(string root, Action<string> fileAction, Action<string> subdirAction, Action<string> noAccessAction)
{
foreach (string file in Directory.GetFiles(root))
{
fileAction(file);
}

foreach (string dir in Directory.GetDirectories(root))
{
try
{
subdirAction(dir);
EnumerateSubDirectories(dir, fileAction, subdirAction, noAccessAction);
}
catch (UnauthorizedAccessException)
{
noAccessAction(dir);
}
}
}
}

How can I get whether directory accessible without try&catch?

This is possible in .NET Core with the GetDirectories, GetFiles, EnumerateDirectories and EnumerateFiles overloads that accept the EnumerationOptions parameter:

var options = new EnumerationOptions { IgnoreInaccessible=true };
var files=Directory.GetDirectories(somePath,"*",options);

EnumerationOptions exists only in .NET Core 2.1 and later, or .NET Standard 2.1 or later. To use it with Windows Forms or WPF applications you'll have to migrate them to .NET (Core) 5 first.

C# - Exclude directories and files from Directory.GetDirectories() and Directory.GetFiles()

what about this:

    var all = Directory.GetFileSystemEntries(path, "*.*",SearchOption.AllDirectories);
var allCount = all.Count();
var noGit = all.Where(p => !p.Contains(@"\.git\") && !p.EndsWith(@"\.git")).ToArray();
var noGitCount = noGit.Count();

UnauthorizedAccessException cannot resolve Directory.GetFiles failure

In order to gain control on the level that you want, you should probably probe one directory at a time, instead of a whole tree. The following method populates the given IList<string> with all files found in the directory tree, except those where the user doesn't have access:

// using System.Linq
private static void AddFiles(string path, IList<string> files)
{
try
{
Directory.GetFiles(path)
.ToList()
.ForEach(s => files.Add(s));

Directory.GetDirectories(path)
.ToList()
.ForEach(s => AddFiles(s, files));
}
catch (UnauthorizedAccessException ex)
{
// ok, so we are not allowed to dig into that directory. Move on.
}
}

Make Directory.GetFiles() ignore protected folders

If you are getting an error when you loop through the files you could throw a try catch around it, log the error and continue processing. Example:

foreach(string filePath in Directory.GetFiles(blah))
{
try
{
//do something with file
}
catch(UnauthorizedAccessException ex)
{
//email yourself about exception or just log it somewhere.
}
}

Access to the path is denied when using Directory.GetFiles(...)

If you want to continue with the next folder after a fail, then yea; you'll have to do it yourself. I would recommend a Stack<T> (depth first) or Queue<T> (bredth first) rather than recursion, and an iterator block (yield return); then you avoid both stack-overflow and memory usage issues.

Example:

    public static IEnumerable<string> GetFiles(string root, string searchPattern)
{
Stack<string> pending = new Stack<string>();
pending.Push(root);
while (pending.Count != 0)
{
var path = pending.Pop();
string[] next = null;
try
{
next = Directory.GetFiles(path, searchPattern);
}
catch { }
if(next != null && next.Length != 0)
foreach (var file in next) yield return file;
try
{
next = Directory.GetDirectories(path);
foreach (var subdir in next) pending.Push(subdir);
}
catch { }
}
}


Related Topics



Leave a reply



Submit