2008-10-05 15 views
62

Estoy tratando de mostrar una lista de todos los archivos encontrados en el directorio seleccionado (y opcionalmente cualquier subdirectorio). El problema que tengo es que cuando el método GetFiles() se encuentra con una carpeta a la que no puede acceder, arroja una excepción y el proceso se detiene.Ignorar carpetas/archivos cuando se niega el acceso a Directory.GetFiles()

¿Cómo ignoro esta excepción (e ignoro la carpeta/archivo protegido) y continúo agregando archivos accesibles a la lista?

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

Otro (marcado como duplicado) pregunta - http://stackoverflow.com/questions/1393178/unauthorizedaccessexception-cannot-resolve-directory-getfiles-failure?noredirect=1 –

Respuesta

42

Tendrá que hacer la recursión manualmente; no use AllDirectories: busque una carpeta a la vez y luego intente obtener los archivos de los subdirectores. No comprobado, pero algo como a continuación (nota utiliza un delegado en lugar de construir una matriz):

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

Demasiado bueno, no he encontrado nada parecido esto en VB.NET. Espero que no te importe si [traduje esto en VB.NET aquí] (http://stackoverflow.com/a/34924036/1197518) – Steve

+3

aún no es suficiente: GetFiles lanza internamente cuando solo un archivo es inaccesible en una carpeta . Entonces toda la carpeta no será tratada. –

2

Esto debería responder la pregunta. He ignorado el problema de ir a través de subdirectorios, supongo que lo has descubierto.

Por supuesto, no necesita tener un método separado para esto, pero puede encontrarlo como un lugar útil para verificar también que la ruta sea válida, y tratar con las otras excepciones que podría encontrar al llamar a GetFiles ()

Espero que esto ayude.

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

ver https://stackoverflow.com/a/10728792/89584 para una solución que maneja el problema de la excepción no autorizada.

Todas las soluciones anteriores perderán archivos y/o directorios si alguna llamada a GetFiles() o GetDirectories() están en carpetas con una combinación de permisos.

+1

todas las soluciones que implican GetFiles/GetDirectories están destinadas a tener el mismo problema, y por lo tanto, son un poco poco elegantes –

2

Sé que esta pregunta es un poco antigua, pero tuve el mismo problema hoy y encontré el siguiente artículo que explica en detalle una solución de "recursión de carpetas".

El artículo reconoce los defectos del método GetDirectories() ...:

Por desgracia, esta [utilizando los GetDirectories() Método] tiene problemas. La clave entre estos es que algunas de las carpetas que intenta leer se pueden configurar para que el usuario actual no pueda acceder a ellas. En lugar de ignorar las carpetas a que tiene acceso restringido, el método arroja una UnauthorizedAccessException. Sin embargo, podemos evitar este problema creando nuestro propio código de búsqueda de carpeta recursiva.

... y luego se introduce la solución en detalle:

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

+0

El más fácil de implementar en mi requerimiento. –

12

Esta función simple funciona bien y cumple con los requisitos de preguntas.

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

Esa es la manera más conveniente y transparente de hacerlo (y) – derFunk

+6

Lamentablemente se detiene en la primera excepción ... –

+1

Sí, debido al error en el manejo de errores, no sirve para nada. Intenta buscar en todo el árbol c: \. Hay una serie de áreas en el sistema de archivos de Windows donde el usuario, incluso con derechos de administrador, no tiene suficientes derechos de acceso. De eso se trata el principal desafío aquí (además de puntos de unión, etc.). – Philm

3

Una forma sencilla de hacerlo es mediante el uso de una lista para archivos y una cola para directorios. Conserve memoria. Si usa un programa recursivo para hacer la misma tarea, eso podría arrojar la excepción OutOfMemory. La salida: los archivos agregados en la Lista están organizados de acuerdo con el árbol de directorios de arriba hacia abajo (ancho primero).

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

Pasos:

  1. Enqueue la raíz de la cola
  2. En un bucle, quitar de la cola, añadir los archivos de ese directorio a la lista, y añadir las subcarpetas a la cola.
  3. Repita hasta que la cola esté vacía.
Cuestiones relacionadas