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.
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.
}
}
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;
}
}
. 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.
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!
dans .NET 4 cela devient beaucoup plus facile, voir http://msdn.microsoft.com/en-us/library/dd997370.aspx
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.
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>();
}
}));
}