3

I am using below LINQ query to get the directory list. I am getting an error (System.UnauthorizedAccessException was unhandled by user code). How to load only the directories to which I have access to.

var files = from f in System.IO.Directory.GetDirectories(@"\\testnetwork\abc$",
                                   "*.*",
                                   SearchOption.AllDirectories)
            select System.IO.Path.GetDirectoryName(f);

Error:

Access to the path '\testnetwork\abc$\DemoFolder\' is denied.

CoolArchTek
  • 3,729
  • 12
  • 47
  • 76

4 Answers4

2

I don't see why you need LINQ for this. Keeping it simple might help to debug the issue. Try something like this:

DirectoryInfo[] directories = System.IO.Directory.GetDirectories(@"\\testnetwork\abc$",
                               "*.*",
                               SearchOption.AllDirectories);
foreach (DirectoryInfo dir in directories)
{
    try
    {
       Console.WriteLine(System.IO.Path.GetDirectoryName(f));
    }
    catch(Exception ex)
    {
       // report an error or something
    }
}
Gigi
  • 28,163
  • 29
  • 106
  • 188
2

The first thing you should do is change the method you are using:

var files = from f in System.IO.Directory.EnumerateDirectories(
        @"\\testnetwork\abc$",
        "*.*",
        SearchOption.AllDirectories)
select f;

EnumerateDirectories works better because it yields the results, and still throws the same exception if it finds a folder where it has no rigths. The fact that it yields the results allows us to compose on top of its output, so if we add an extension method like this:

static class ExceptionExtensions
{
    public static IEnumerable<TIn> Catch<TIn>(
                this IEnumerable<TIn> source,
                Type exceptionType)
    {   
        using (var e = source.GetEnumerator())
        while (true)
        {
            var ok = false;

            try
            {
                ok = e.MoveNext();
            }
            catch(Exception ex)
            {
                if (ex.GetType() != exceptionType)
                    throw;
                continue;
            }

            if (!ok)
                yield break;

            yield return e.Current;
        }
    }
}

then we are allowed to write something like this:

var files = from f in System.IO.Directory.EnumerateDirectories(
        @"\\testnetwork\abc$",
        "*.*",
        SearchOption.AllDirectories)
        .Catch(typeof(UnauthorizedAccessException))
select f;

and your output should be the expected one while still keeping the Linq expression clean and composable. The idea of the Catch method is to "swallow" the exception you don't want around without preventing the other ones from happening. It's a draft implementation, but you get the idea.

Wasp
  • 3,395
  • 19
  • 37
1

I believe there are properties called "CanRead" and "CanWrite" on the File and Directory classes in the System.IO namespace. You could use those to determine whether you have rights.

The other way that I know of would be to use Code Access Security and write a method that "Demands" the appropriate privileges....

Sorry, I'm just about to go into a meeting, but I've given you enough to Google with. I'll write more later if this question is still without a solid answer.

Robert Iver
  • 711
  • 2
  • 9
  • 14
1

Catch the UnauthorizedAccessException using Catch. .

  string[] directories = Directory.EnumerateDirectories(@"\\testnetwork\abc$","*.*", SearchOption.AllDirectories).Catch(typeof(UnauthorizedAccessException)).ToArray();

ExceptionExtensions:

   static class ExceptionExtensions
{
public static IEnumerable<TIn> Catch<TIn>(
            this IEnumerable<TIn> source,
            Type exceptionType)
{   
    using (var e = source.GetEnumerator())
    while (true)
    {
        var ok = false;

        try
        {
            ok = e.MoveNext();
        }
        catch(Exception ex)
        {
            if (ex.GetType() != exceptionType)
                throw;
            continue;
        }

        if (!ok)
            yield break;

        yield return e.Current;
    }
}
}
Jignesh Thakker
  • 3,638
  • 2
  • 28
  • 35
  • Are you sure this one works? `GetDirectories` processes the folders as a whole, and if there is one single folder causing the unauthorized access you will not be able to see any output, just the exception. At least that's what I saw testing it. – Wasp Sep 11 '12 at 23:10
  • I updated my answer @Wasp as you mentioned we need extension method. – Jignesh Thakker Sep 12 '12 at 06:14