简体   繁体   中英

C# Handle System.UnauthorizedAccessException in LINQ

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.

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
    }
}

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.

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.

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;
    }
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM