L'exception d'accès non autorisé ne peut pas résoudre le répertoire.Échec de GetFiles [dupliquer]

cette question a déjà une réponse ici:

Directory.La méthode GetFiles échoue lors de la première rencontre avec un dossier auquel il n'a pas de droits d'accès.

la méthode jette une exception D'accès non autorisée (qui peut être capturée) mais au moment où cela est fait, la méthode a déjà échoué/terminé.

le code que j'utilise est indiqué ci-dessous:

try
{
    // looks in stated directory and returns the path of all files found                
    getFiles = Directory.GetFiles(
        @directoryToSearch, 
        filetype, 
        SearchOption.AllDirectories);             
}
catch (UnauthorizedAccessException) 
{ 
}

autant que je sache, il n'y a aucun moyen de vérifier à l'avance si un certain dossier a des droits d'accès définis.

dans mon exemple, je cherche sur un disque à travers un réseau et quand je tombe sur un accès root seulement dossier de mon programme échoue.

22
demandé sur yanckst 2009-09-08 14:23:45

7 réponses

afin de prendre le contrôle sur le niveau que vous voulez, vous devriez probablement sonder un répertoire à la fois, au lieu d'un arbre entier. La méthode suivante popule la donnée IList<string> avec tous les fichiers trouvés dans l'arborescence du répertoire, sauf ceux auxquels l'utilisateur n'a pas accès:

// 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.
    }
}
17
répondu Fredrik Mörk 2009-09-08 10:32:23

ceci est une amélioration de la réponse de Malcolm (http://stackoverflow.com/a/9831340/226181). Cela scanne tous les disques logiques pour un motif de correspondance de fichier et ignore les répertoires qui ne sont pas accessibles.

 static List<string> SearchFiles(string pattern)
    {
        var result = new List<string>();

        foreach (string drive in Directory.GetLogicalDrives())
        {
            Console.WriteLine("searching " + drive);
            var files = FindAccessableFiles(drive, pattern, true);
            Console.WriteLine(files.Count().ToString() + " files found.");
            result.AddRange(files);
        }

        return result;
    }

    private static IEnumerable<String> FindAccessableFiles(string path, string file_pattern, bool recurse)
    {
        Console.WriteLine(path);
        var list = new List<string>();
        var required_extension = "mp4";

        if (File.Exists(path))
        {
            yield return path;
            yield break;
        }

        if (!Directory.Exists(path))
        {
            yield break;
        }

        if (null == file_pattern)
            file_pattern = "*." + required_extension;

        var top_directory = new DirectoryInfo(path);

        // Enumerate the files just in the top directory.
        IEnumerator<FileInfo> files;
        try
        {
            files = top_directory.EnumerateFiles(file_pattern).GetEnumerator();
        }
        catch (Exception ex)
        {
            files = null;
        }

        while (true)
        {
            FileInfo file = null;
            try
            {
                if (files != null && files.MoveNext())
                    file = files.Current;
                else
                    break;
            }
            catch (UnauthorizedAccessException)
            {
                continue;
            }
            catch (PathTooLongException)
            {
                continue;
            }

            yield return file.FullName;
        }

        if (!recurse)
            yield break;

        IEnumerator<DirectoryInfo> dirs;
        try
        {
            dirs = top_directory.EnumerateDirectories("*").GetEnumerator();
        }
        catch (Exception ex)
        {
            dirs = null;
        }


        while (true)
        {
            DirectoryInfo dir = null;
            try
            {
                if (dirs != null && dirs.MoveNext())
                    dir = dirs.Current;
                else
                    break;
            }
            catch (UnauthorizedAccessException)
            {
                continue;
            }
            catch (PathTooLongException)
            {
                continue;
            }

            foreach (var subpath in FindAccessableFiles(dir.FullName, file_pattern, recurse))
                yield return subpath;
        }
    }
4
répondu matrix 2012-05-26 15:17:41

. Annuaire de Net 4.EnumerateFiles ne fonctionne, mais vous devez faire attention à la façon dont vous évaluez l'énumérable et de faire cette partie à l'intérieur du bloc try-catch. Le plus gros problème est de s'assurer que vous n'arrêtez pas le traitement à la première exception (qui je pense réponse https://stackoverflow.com/a/1393219/89584 ci-dessus a ce problème, s'il vous plaît corriger moi si je me trompe).

les travaux suivants et vous donne un énumérable de sorte que vous n'avez pas à évaluez la totalité de l'arborescence des fichiers si vous recherchez la première correspondance, etc.

private IEnumerable<String> FindAccessableFiles(string path, string file_pattern, bool recurse)
{
  IEnumerable<String> emptyList = new string[0];

  if (File.Exists(path))
    return new string[] { path };

  if (!Directory.Exists(path))
    return emptyList;

  var top_directory = new DirectoryInfo(path);

  // Enumerate the files just in the top directory.
  var files = top_directory.EnumerateFiles(file_pattern);
  var filesLength = files.Count();
  var filesList = Enumerable
            .Range(0, filesLength)
            .Select(i =>
            {
              string filename = null;
              try
              {
                var file = files.ElementAt(i);
                filename = file.FullName;
              }
              catch (UnauthorizedAccessException)
              {
              }
              catch (InvalidOperationException)
              {
                    // ran out of entries
              }
              return filename;
            })
            .Where(i => null != i);

        if (!recurse)
          return filesList;

        var dirs = top_directory.EnumerateDirectories("*");
        var dirsLength = dirs.Count();
        var dirsList = Enumerable
            .Range(0, dirsLength)
            .SelectMany(i =>
            {
              string dirname = null;
              try
              {
                var dir = dirs.ElementAt(i);
                dirname = dir.FullName;
                return FindAccessableFiles(dirname, file_pattern, required_extension, recurse);
              }
              catch (UnauthorizedAccessException)
              {
              }
              catch (InvalidOperationException)
              {
                 // ran out of entries
              }

              return emptyList;
            })

  return Enumerable.Concat(filesList, dirsList);
}

améliorations à l'accueil ci-dessus.

4
répondu Malcolm 2017-05-23 12:34:38

je sais que ce fil est vieux, mais au cas où quelqu'un trébuche sur ce et a besoin d'une réponse, j'ai une solution récursive ici:

public static List<string> GetAllAccessibleFiles(string rootPath, List<string> alreadyFound = null)
    {
        if (alreadyFound == null)
            alreadyFound = new List<string>();
        DirectoryInfo di = new DirectoryInfo(rootPath);
        var dirs = di.EnumerateDirectories();
        foreach (DirectoryInfo dir in dirs)
        {
            if (!((dir.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden))
            {
                alreadyFound = GetAllAccessibleFiles(dir.FullName, alreadyFound);
            }
        }

        var files = Directory.GetFiles(rootPath);
        foreach (string s in files)
        {
            alreadyFound.Add(s);                
        }

        return alreadyFound;
    }

il retourne un List<string> contenant le chemin complet vers tous les fichiers qui sont dans les répertoires accessibles sous le répertoire racine donné. Appelez-le comme ceci:

var files = GetAllAccessibleFiles(@"C:\myDirectory");

donc un résultat pourrait être comme ceci:

C:\myDirectory\a\a.txt
C:\myDirectory\a\b.mp3
C:\myDirectory\b\a\a\foo.txt
C:\myDirectory\b\b\b\hello.exe
C:\myDirectory\b\c\bar.jpg
C:\myDirectory\and\so\on.bar
C:\myDirectory\a_file_in_root.bmp

Espère que cela aide quelqu'un!

4
répondu schnaidar 2013-12-22 19:34:55

dans .NET 4 cela devient beaucoup plus facile, voir http://msdn.microsoft.com/en-us/library/dd997370.aspx

3
répondu Ian Mercer 2010-04-18 20:10:17
public string[] GetFilesFrom(string dir, string search_pattern, bool recursive)
{
    List<string> files = new List<string>();

    string[] temp_files = new string[0];

    try { temp_files = Directory.GetFiles(dir, search_pattern, SearchOption.TopDirectoryOnly); }
    catch { }

    files.AddRange(temp_files);

    if (recursive)
    {
        string[] temp_dirs = new string[0];

        try { temp_dirs = Directory.GetDirectories(dir, search_pattern, SearchOption.TopDirectoryOnly); }
        catch { }

        for (int i = 0; i < temp_dirs.Length; i++)
            files.AddRange(GetFilesFrom(temp_dirs[i], search_pattern, recursive));
    }

    return files.ToArray();
}

C'est ma solution pour ce problème. Simple et sûre.

1
répondu Kosmos 2014-10-06 17:27:38

la version la plus simple:

IEnumerable<String> GetAllFiles(string path, string searchPattern)
{
    return System.IO.Directory.EnumerateFiles(path, searchPattern).Union(
        System.IO.Directory.EnumerateDirectories(path).SelectMany(d =>
        {
            try
            {
                return GetAllFiles(d, searchPattern);
            }
            catch (UnauthorizedAccessException e)
            {
                return Enumerable.Empty<String>();
            }
        }));
}
0
répondu Bohdan 2015-02-19 16:41:53