2011-02-13 44 views
10

Estoy ejecutando el siguiente código y obteniendo la excepción a continuación. ¿Estoy obligado a poner esta función en try catch o hay otra forma de obtener todos los directorios recursivamente? Podría escribir mi propia función recursiva para obtener archivos y directorios. Pero me pregunto si hay una mejor manera.Se niega el acceso a la ruta cuando se utiliza Directory.GetFiles (...)

// get all files in folder and sub-folders 
var d = Directory.GetFiles(@"C:\", "*", SearchOption.AllDirectories); 

// get all sub-directories 
var dirs = Directory.GetDirectories(@"C:\", "*", SearchOption.AllDirectories); 

"Acceso a la ruta 'C: \ Documents and Settings \' denegado."

+0

posible duplicado de [Ignorar carpetas/archivos cuando Directory.GetFiles() se les niega el acceso] (http://stackoverflow.com/questions/172544/ignore-folders-files-when-directory-getfiles-is -denied-access) – Ani

+0

@Ani ¡Gracias! Para señalar eso. Sin embargo, no encuentro ninguna respuesta lo suficientemente buena. Me gustaría obtener una solución alternativa. –

Respuesta

30

Si desea continuar con la siguiente carpeta después de un error, entonces sí; tendrás que hacerlo tú mismo. Recomendaría un Stack<T> (profundidad primero) o Queue<T> (primero en comparación) en lugar de recursión, y un bloque de iterador (yield return); entonces evita tanto problemas de desbordamiento de pila como de uso de memoria.

Ejemplo:

public static IEnumerable<string> GetFiles(string root, string searchPattern) 
    { 
     Stack<string> pending = new Stack<string>(); 
     pending.Push(root); 
     while (pending.Count != 0) 
     { 
      var path = pending.Pop(); 
      string[] next = null; 
      try 
      { 
       next = Directory.GetFiles(path, searchPattern);      
      } 
      catch { } 
      if(next != null && next.Length != 0) 
       foreach (var file in next) yield return file; 
      try 
      { 
       next = Directory.GetDirectories(path); 
       foreach (var subdir in next) pending.Push(subdir); 
      } 
      catch { } 
     } 
    } 
+1

+1 @Marc Gracias por dar una solución alternativa. Ahora que me diste una alternativa a la recursividad, ¿podrías dar un ejemplo? –

+0

@Amir - example added –

+0

Esto es realmente extraño, pero no puedo depurar tu código. El depurador no interrumpe mis puntos de interrupción, ni siquiera cuando escribo Debugger.Break(); en tu función. Como que salto sobre tu código. –

2

Bueno, o bien evitar los directorios para el que no tiene permisos, o si no responde con gracia pero luego cuando se deniega el acceso.

Si elige la primera opción, deberá asegurarse de saber qué directorios son y que los permisos para la identidad del hilo no cambian. Esto es complicado y propenso al error; No lo recomendaría para un sistema de calidad de producción.

La segunda opción parece más apropiada. Use un bloque try/catch y omita cualquier directorio "prohibido".

7

Puede configurar el programa para que solo pueda ejecutarlo como administrador.

En Visual Studio:

Right click on the Project -> Properties -> Security -> Enable ClickOnce Security Settings 

Después de clic, un archivo se creará en las propiedades del proyecto carpeta llamada app.manifest una vez que este se crea, puede desmarcar la opción Enable ClickOnce Security Settings

Abrir el archivo y cambiar esta línea:

<requestedExecutionLevel level="asInvoker" uiAccess="false" /> 

a:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> 

Esto hará que el programa requiere privilegios de administrador, y garantizará que tenga acceso a esa carpeta.

+3

No * necesariamente * la solución predeterminada para un problema de acceso denegado ... –

+0

No, pero es una opción. –

+0

+1 Buena alternativa. –

0

Sé que esta pregunta es algo 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

Ya se ha señalado que es necesario hacerlo por sí solo, así que pensé que me gustaría compartir mi solución que evita colecciones en el camino. Cabe señalar que esto ignorará todos los errores, no solo AccessDenied. Para cambiar eso, puedes hacer que los bloques catch sean más específicos.

IEnumerable<string> GetFiles(string folder, string filter, bool recursive) 
    { 
     string [] found = null; 
     try 
     { 
      found = Directory.GetFiles(folder, filter); 
     } 
     catch { } 
     if (found!=null) 
      foreach (var x in found) 
       yield return x; 
     if (recursive) 
     { 
      found = null; 
      try 
      { 
       found = Directory.GetDirectories(folder); 
      } 
      catch { } 
      if (found != null) 
       foreach (var x in found) 
        foreach (var y in GetFiles(x, filter, recursive)) 
         yield return y; 
     } 
    } 
Cuestiones relacionadas