Listar ficheros

Iniciado por Tomas1982, 22 Septiembre 2016, 23:40 PM

0 Miembros y 1 Visitante están viendo este tema.

Tomas1982

Estoy tratando de listar los archivo de las unidades de disco encontradas pero me da error (Acceso denegado). Este es el código que estoy usando.  
Código (vbnet) [Seleccionar]

For Each vUnidad As String In Directory.GetLogicalDrives()
ListBox1.Items.Add(vUnidad)
Next vUnidad
'Recorrer las unidades detectadas
Dim Pdisco As String
For i As Integer = 0 To Me.ListBox1.Items.Count - 1
Pdisco = ListBox1.Items(i)
'Obtener los ficheros de las unidades
filepaths = Directory.GetFiles(Pdisco, "*", SearchOption.AllDirectories)
ListBox2.Items.Add(filepaths)
Next

okik

#1
Hay dos tipos de error el de la unidad que no está disponible como un DVD-ROM, una disquetera. Y otro es carpetas que no se pueden abrir por estar protegidas por el sistema.

Puedes usar Try/Catch para saltar el error o también, pero te van a regañar,  "On Error Resume Next"

Código (vbnet) [Seleccionar]
 

        Task.Factory.StartNew(Sub()
                                  Me.Invoke(Sub() Me.Cursor = Cursors.WaitCursor)

                                  For Each vUnidad As String In Directory.GetLogicalDrives()


                                      ListBox1.Invoke(DirectCast(Sub() ListBox1.Items.Add(vUnidad), MethodInvoker))
                                  Next vUnidad

                                  ''Recorrer las unidades detectadas
                                  Dim Pdisco As String
                                  For i As Integer = 0 To Me.ListBox1.Items.Count - 1
                                      Pdisco = CStr(ListBox1.Items(i))

                                      'Obtener los ficheros de las unidades
                                      Try
                                          Dim DirInfo As New DirectoryInfo(Pdisco)
                                          For Each Files As System.IO.FileInfo In DirInfo.GetFiles("*", SearchOption.TopDirectoryOnly)
                                              ListBox2.Invoke(DirectCast(Sub() ListBox2.Items.Add(Pdisco & Files.ToString), MethodInvoker))
                                          Next
                                      Catch ex As Exception
                                      End Try
                                  Next
                              End Sub).ContinueWith(Sub()
                                                        Me.Invoke(Sub() Me.Cursor = Cursors.Arrow)
                                                    End Sub)
 




De todos modos solo te va a listar los archivos inmediatos de un directorio pero no todos los archivos únicos de cada directorio y subdirectorios como carpetas y demás. Ni tampoco archivos ocultos. Por no decir que ese código no está bien implementado para ese objetivo.

Te lo he metido dentro de Task.Factory.StartNew(Sub() End Sub) para evitar que el programa se quede bloqueado mientras busca.

Ahora mismo no tengo nada para listar absolutamente todos los archivos y archivos ocultos. Tendría que mirármelo, porque nunca lo he hecho, por lo menos con VB.NET

chau




he estado mirándome el tema y esto sería creo más o menos lo que buscas pero..... como digo no lista todos los archivos, en este caso los de un directorio y sus subdirectorios.


Código (vbnet) [Seleccionar]

       Dim strDirPath As String = "C:\"

       Dim astrSubDirectories As String() = Directory.GetDirectories(strDirPath)
       Dim strSubDirectory As String
       For Each strSubDirectory In astrSubDirectories
           Dim direct As String = strSubDirectory.Remove(0, strSubDirectory.LastIndexOf("\") + 1)

           Try
               Dim astrFiles As String() = Directory.GetFiles(strDirPath & direct)
               ListBox1.Items.Add(strSubDirectory)
               For Each strFileName In astrFiles
                   ListBox1.Items.Add(strFileName)
               Next

           Catch exc As Exception

           End Try
       Next

       Try
           Dim DirInfo As New DirectoryInfo(strDirPath)
           For Each Files As System.IO.FileInfo In DirInfo.GetFiles("*", SearchOption.TopDirectoryOnly)
               ListBox1.Items.Add(strDirPath & Files.ToString)
           Next
       Catch ex As Exception
       End Try


El error de Acceso denegado, es porque hay carpetas protegidas por el sistema como Document and Settings que no deja que sean abiertas.





Código (vbnet) [Seleccionar]
      Dim allDrives() As DriveInfo = DriveInfo.GetDrives()
       For Each [Drive] In allDrives
           Try
               Dim astrSubDirectories As String() = Directory.GetDirectories([Drive].ToString)
               Dim strSubDirectory As String
               For Each strSubDirectory In astrSubDirectories
                   Dim direct As String = strSubDirectory.Remove(0, strSubDirectory.LastIndexOf("\") + 1)

                   Try
                       Dim astrFiles As String() = Directory.GetFiles([Drive].ToString & direct)
                       ListBox1.Items.Add(strSubDirectory)
                       For Each strFileName In astrFiles
                           ListBox1.Items.Add(strFileName)
                       Next

                   Catch exc As Exception

                   End Try
               Next

               Try
                   Dim DirInfo As New DirectoryInfo([Drive].ToString)
                   For Each Files As System.IO.FileInfo In DirInfo.GetFiles("*", SearchOption.TopDirectoryOnly)
                       ListBox1.Items.Add([Drive].ToString & Files.ToString)
                   Next
               Catch ex As Exception
              'MessageBox.Show(ex.Message)
               End Try
           Catch ex As Exception
             'MessageBox.Show(ex.Message)
           End Try

       Next






Pues finalmente creo que di con la solución. Bastaba con añadir esto , "*", SearchOption.AllDirectories a al código anterior:

Dim astrFiles As String() = Directory.GetFiles("C:\" & direct, "*", SearchOption.AllDirectories)


Aquí te muestra todos los archivos de un directorio (con la ruta completa)[/size]

Código (vbnet) [Seleccionar]

            Dim strDrive As String = "D:\" '[Drive].ToString
       Dim DriveSubDirectories As String() = Directory.GetDirectories(strDrive)
       For Each strSubDirectory As String In DriveSubDirectories
           Dim strFolder As String = strSubDirectory.Remove(0, strSubDirectory.LastIndexOf("\") + 1)
           ListBox1.Items.Add(strSubDirectory) '<---Carpeta
           Try
               Dim strFiles As String() = Directory.GetFiles(strDrive & strFolder, "*", SearchOption.AllDirectories)
               For Each strFileName In strFiles
                   ListBox1.Items.Add(strFileName) '<--Archivo con ruta completa
               Next
           Catch ex As Exception
               '   MessageBox.Show(ex.Message)
           End Try 'strFiles
       Next   'strSubDirectory
       Try
           Dim DirInfo As New DirectoryInfo(strDrive)
           For Each Files As System.IO.FileInfo In DirInfo.GetFiles("*", SearchOption.TopDirectoryOnly)
               ListBox1.Items.Add(strDrive & Files.ToString)
           Next
       Catch ex As Exception
       End Try 'DirInfo



Pero tarda bastante... según el número de archivos y subdirectorios...

Para obtener todos de todas las unidades

Código (vbnet) [Seleccionar]
 
          Dim allDrives() As DriveInfo = DriveInfo.GetDrives()
       For Each [Drive] In allDrives
           Try
               Dim strDrive As String = [Drive].ToString
               Dim DriveSubDirectories As String() = Directory.GetDirectories(strDrive)
               For Each strSubDirectory As String In DriveSubDirectories
                   Dim strFolder As String = strSubDirectory.Remove(0, strSubDirectory.LastIndexOf("\") + 1)
                   ListBox1.Items.Add(strSubDirectory) '<---Carpeta
                   Try
                       Dim strFiles As String() = Directory.GetFiles(strDrive &
                                                                     strFolder,
                                                                     "*",
                                                                     SearchOption.AllDirectories)
                       For Each strFileName In strFiles
                           ListBox1.Items.Add(strFileName) '<--Archivo con ruta completa
                       Next 'strFileName
                   Catch ex As Exception
                       '   MessageBox.Show(ex.Message)
                   End Try 'strFiles
               Next  'strSubDirectory

               Try
                   Dim DirInfo As New DirectoryInfo(strDrive)
                   For Each Files As System.IO.FileInfo In DirInfo.GetFiles("*", SearchOption.TopDirectoryOnly)
                       ListBox1.Items.Add(strDrive & Files.ToString)
                   Next 'Files
               Catch ex As Exception
                   '   MessageBox.Show(ex.Message)
               End Try 'DirInfo

           Catch ex As Exception
               MessageBox.Show(ex.Message)
           End Try 'Drives
       Next '[Drive]



Pero te va a tardar un guevo  :xD

**Se me olvidaba, para ver los archivos ocultos y otros protegidos del sistema basta con ejecutar la aplicación con privilegios de administrador.

Eleкtro

#2
@okik

Un consejo, cuando el factor de la velocidad sea un requisito primordial entonces no uses las funciones Directory.Get***, en su lugar usa Directory.Enumerate***, así evitarás que se inicialicen todos los elementos de golpe en la colección.

Por lo demás, buen código, nada más que objetar, aunque el try/catch se puede remplazar por una evaluación de los permisos ACL del directorio, pero bueno, el resultado al fin y al cabo sería el mismo y con un try/catch se reduce bastante el tamaño del código resultante.

Saludos!








okik

@Elektro he hecho lo que me has dicho.

Código (vbnet) [Seleccionar]
Dim strFiles As IEnumerable = Directory.EnumerateFiles(strDrive & strFolder, "*", SearchOption.AllDirectories)

No he notado mucho la diferencia, pero supongo que algo hará. De todos modos es bueno conocer otras maneras. Cuando respondí, lo que hice en un principio fue probar el código  de @Tomas1982  y vi que no andaba bien y empecé a investigar, pero no  había hecho nunca con Net un buscador de archivos. Busqué en MSDN y ponían el Get.. y eso hice  :P Se ve la evolución en mi respuesta XD

Igualito que en VB, madre mía, no había que escribir ni nada para hacer eso. Pero molaba porque tenías que pensar y te daba ese gusanillo mental que cuando lo conseguías era como si te tocara la lotería.  Net es engorroso porque todo se basa en miembros y clases. Conocerlos todos, si es posible, es tedioso y fastidia cuando haces algo de diez líneas y luego descubres que hay una clase que te hace lo mismo en una. Otra cosa que fastidia son las actualizaciones y los métodos obsoletos. Que en la 2005 o 2010 se podían usar y luego en 2015 ya no, o al revés. Que palo.








Eleкtro

#4
Cita de: okik en 24 Septiembre 2016, 13:25 PM
@Elektro he hecho lo que me has dicho.

Código (vbnet) [Seleccionar]
Dim strFiles As IEnumerable = Directory.EnumerateFiles(strDrive & strFolder, "*", SearchOption.AllDirectories)

No he notado mucho la diferencia, pero supongo que algo hará.

La diferencia está en que la colección Enumerable se devuelve practicamente al instante (mientras que Directory.GetFiles(...) tarda lo suyo como ya has comprobado) puesto que los elementos no se inicializan, por así decirlo, hasta que lo demandes, en este caso sería cuando iteras los elementos de la colección usando el FOR en tu código, por eso no notas una diferencia en velocidad, pero la hay, y aporta otros beneficios también.




Cita de: okik en 24 Septiembre 2016, 13:25 PMNet es engorroso porque todo se basa en miembros y clases.

Bueno, quizás te parezca "engorroso" por que no estarás lo suficientemente acostumbrado al paradigma de programación orientado a objetos... pero eso es precisamente lo que hace tan versátiles y moldeables a este tipo de lenguajes.




Cita de: okik en 24 Septiembre 2016, 13:25 PMConocerlos todos, si es posible, es tedioso y fastidia cuando haces algo de diez líneas y luego descubres que hay una clase que te hace lo mismo en una.

Ya, eso nos ha pasado a todos, jeje!

Conocer todos los types y/o miembros de la librería de classes de .NET Framework es sencillamente algo imposible, es un set de librerías demasiado extenso y el cerebro humano no da para tanto, pero tampoco es necesario intentar conocerlo todo por que todo no lo vas a usar, eso sí, lo esencial es imprescindible conocerlo... y te recomiendo leer sobre Generics en .NET, si lo dominas te resultará una forma de programación muy util, la más util tal vez.

Saludos!








Tomas1982

Gracias por la ayuda, el código esta muy bueno, espero que a otros usuarios también les sea muy útil.