2008-10-05 8 views
62

J'essaie d'afficher une liste de tous les fichiers trouvés dans le répertoire sélectionné (et éventuellement dans les sous-répertoires). Le problème que j'ai est que quand la méthode GetFiles() rencontre un dossier auquel elle ne peut pas accéder, elle lance une exception et le processus s'arrête. Comment puis-je ignorer cette exception (et ignorer le dossier/fichier protégé) et continuer à ajouter des fichiers accessibles à la liste?Ignorer les dossiers/fichiers lorsque Directory.GetFiles() se voit refuser l'accès

try 
{ 
    if (cbSubFolders.Checked == false) 
    { 
     string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath); 
     foreach (string fileName in files) 
      ProcessFile(fileName); 
    } 
    else 
    { 
     string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories); 
     foreach (string fileName in files) 
      ProcessFile(fileName); 
    } 
    lblNumberOfFilesDisplay.Enabled = true; 
} 
catch (UnauthorizedAccessException) { } 
finally {} 
+0

Un autre (marqué comme double) question - http://stackoverflow.com/questions/1393178/unauthorizedaccessexception-cannot-resolve-directory-getfiles-failure?noredirect=1 –

Répondre

42

Vous devrez effectuer la récursion manuellement; n'utilisez pas AllDirectories - regardez un dossier à la fois, puis essayez d'obtenir les fichiers des sous-répertoires. Non testé, mais quelque chose comme ci-dessous (note utilise un délégué plutôt que de construire un tableau):

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

Trop bon, je ne l'ai pas trouvé quoi que ce soit comme ceci dans VB.NET. J'espère que cela ne vous dérange pas si j'ai [traduit cela dans VB.NET ici] (http://stackoverflow.com/a/34924036/1197518) – Steve

+3

toujours pas assez: GetFiles se lance en interne lorsqu'un seul fichier est inaccessible dans un dossier . Donc, le dossier entier ne sera pas traité. –

2

Cela devrait répondre à la question. J'ai ignoré la question de passer en revue les sous-répertoires, je suppose que vous avez compris.

Bien sûr, vous n'avez pas besoin d'avoir une méthode séparée pour cela, mais vous pourriez trouver utile de vérifier que le chemin est valide et de gérer les autres exceptions que vous pourriez rencontrer lors de l'appel de GetFiles ().

Espérons que cela aide.

private string[] GetFiles(string path) 
{ 
    string[] files = null; 
    try 
    { 
     files = Directory.GetFiles(path); 
    } 
    catch (UnauthorizedAccessException) 
    { 
     // might be nice to log this, or something ... 
    } 

    return files; 
} 

private void Processor(string path, bool recursive) 
{ 
    // leaving the recursive directory navigation out. 
    string[] files = this.GetFiles(path); 
    if (null != files) 
    { 
     foreach (string file in files) 
     { 
      this.Process(file); 
     } 
    } 
    else 
    { 
     // again, might want to do something when you can't access the path? 
    } 
} 
1

voir https://stackoverflow.com/a/10728792/89584 pour une solution qui gère le problème UnauthorisedAccessException.

Toutes les solutions ci-dessus manqueront des fichiers et/ou des répertoires si des appels à GetFiles() ou GetDirectories() se trouvent dans des dossiers avec un mélange d'autorisations.

+1

toutes les solutions impliquant GetFiles/GetDirectories sont liées au même problème, et sont donc un peu inélégant –

2

Je sais que cette question est un peu ancienne, mais j'ai eu ce même problème aujourd'hui et j'ai trouvé l'article suivant qui explique en détail une solution de "récurrence de dossier".

L'article reconnaît les défauts de la méthode GetDirectories() ...:

Malheureusement, cette [en utilisant la méthode GetDirectories()] a des problèmes. La clé parmi ceux-ci est que certains des dossiers que vous essayez de lire peuvent être configurés de sorte que l'utilisateur actuel ne peut pas y accéder. Plutôt que d'ignorer les dossiers vers auxquels vous avez restreint l'accès, la méthode renvoie une exception UnauthorizedAccessException . Cependant, nous pouvons contourner ce problème en créant notre propre code de recherche de dossier récursif.

... et introduit alors la solution en détail:

http://www.blackwasp.co.uk/FolderRecursion.aspx

+0

Plus facile à mettre en œuvre dans mon exigence. –

12

Cette fonction simple fonctionne bien et répond aux exigences des questions.

private List<string> GetFiles(string path, string pattern) 
{ 
    var files = new List<string>(); 

    try 
    { 
     files.AddRange(Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)); 
     foreach (var directory in Directory.GetDirectories(path)) 
      files.AddRange(GetFiles(directory, pattern)); 
    } 
    catch (UnauthorizedAccessException) { } 

    return files; 
} 
+0

C'est la manière la plus pratique et la plus transparente de le faire (y) – derFunk

+6

Malheureusement, il s'arrête à la première exception ... –

+1

Oui, en raison de la gestion des erreurs manquantes, il est peu utilisé. Essayez simplement de rechercher tout l'arbre c: \. Il y a un certain nombre de zones dans le système de fichiers Windows où l'utilisateur peut-être même avec des droits d'administrateur n'a pas assez de droits d'accès. C'est ce que le principal défi est ici (en dehors des points de jonction, et autres). – Philm

3

Une manière simple d'y parvenir consiste à utiliser une liste pour les fichiers et une file d'attente pour les répertoires. Il conserve la mémoire. Si vous utilisez un programme récursif pour effectuer la même tâche, cela peut générer une exception OutOfMemory. La sortie: les fichiers ajoutés dans la liste sont organisés selon l'arborescence de répertoires de haut en bas (largeur en premier).

public static List<string> GetAllFilesFromFolder(string root, bool searchSubfolders) { 
    Queue<string> folders = new Queue<string>(); 
    List<string> files = new List<string>(); 
    folders.Enqueue(root); 
    while (folders.Count != 0) { 
     string currentFolder = folders.Dequeue(); 
     try { 
      string[] filesInCurrent = System.IO.Directory.GetFiles(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); 
      files.AddRange(filesInCurrent); 
     } 
     catch { 
      // Do Nothing 
     } 
     try { 
      if (searchSubfolders) { 
       string[] foldersInCurrent = System.IO.Directory.GetDirectories(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); 
       foreach (string _current in foldersInCurrent) { 
        folders.Enqueue(_current); 
       } 
      } 
     } 
     catch { 
      // Do Nothing 
     } 
    } 
    return files; 
} 

Étapes:

  1. Enqueue la racine dans la file d'attente
  2. Dans une boucle, Dequeue, ajoutez les fichiers dans ce répertoire à la liste, et ajoutez les sous-dossiers à la file d'attente.
  3. Répéter jusqu'à ce que la file d'attente soit vide.
Questions connexes