Problemas a listar Archivos

Iniciado por OscarCadenas_91, 3 Febrero 2015, 18:42 PM

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

OscarCadenas_91


Hola a todos soy nuevo en este foro.

Comence hace 3 semanas a aprender VB.NET y despues de leer y leer  queria hacer mi primer programa es muy sencillo pero lo necesitaba, el programa lo que hace es buscar archivos con extension ".docx" y ".pptx" de mi memoria usb para luego copiar en otra carpeta, hasta hace un par de dias funcionaba, buscaba archivos y los mostraba en un listview1, pero ayer me infecte con un virus mi usb y oculto todas los archivos y carpetas y mi antivirus borro el virus, pero aun estaban ocultos los archivos y crei que igual deberia listar los archivos sin importar los atributos de oculto, pero cuando le doy a buscar me muestra el siguiente error:

No se controló StackOverflowException

Excepción no controlada del tipo 'System.StackOverflowException' en mscorlib.dll

Despues busque la forma de volver a mostrar los archivos desde el CMD de windows encontre que el virus movio todos mis archivos en una carpeta sin nombre(me di cuenta despues que el nombre tenia un espacio si no me equivoco es un caracter que aparece cuando se presiona alt + 0160).

El problema ocurre con esa carpeta con nombre vacio ya que si le cambio de nombre de la carpeta la aplicacion funciona.

Aqui les dejo el codigo del boton buscar archivos:


Código (vbnet) [Seleccionar]
'BOTON BUSCAR ARCHIVOS
Try
            Dim RutaArchivos As String = "G:\"

            For Each archivo As String In My.Computer.FileSystem.GetFiles(RutaArchivos, FileIO.SearchOption.SearchAllSubDirectories, "*.docx")
                ListView1.Items.Add(archivo)
            Next
For Each archivo2 As String In My.Computer.FileSystem.GetFiles(RutaArchivos, FileIO.SearchOption.SearchAllSubDirectories, "*.pptx")
                ListView1.Items.Add(archivo2)
            Next
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try


Si alguien podria ayudarme a solucionarlo, se lo agradeceria mucho.


Eleкtro

#1
Cita de: OscarCadenas_91 en  3 Febrero 2015, 18:42 PMestaban ocultos los archivos y crei que igual deberia listar los archivos sin importar los atributos de oculto

Efectivamente, la función GetFiles lista los archivos sin importar sus atributos.

No es necesario realizar cambios, aunque debo decir que para simplificar el código puedes utilizar el overload del método My.Computer.FileSystem.GetFiles que acepta un array de extensiones, en lugar de realizar dos búsquedas distintas como estás haciendo ...eso es algo innecesario:

Código (vbnet) [Seleccionar]
Imports Microsoft.VisualBasic.FileIO

Public Class TestForm

   Private Sub TestForm_Shown() Handles MyBase.Shown

       Dim folderPath As String = "C:\"
       Dim fileExts As IEnumerable(Of String) = {"*.docx", "*.pptx"}
       Dim filePaths As IEnumerable(Of String)
       Dim lvItems As IEnumerable(Of ListViewItem)

       Try
           filePaths = From filePath As String In My.Computer.FileSystem.GetFiles(folderPath,
                                                                                  SearchOption.SearchAllSubDirectories,
                                                                                  fileExts.ToArray)
       Catch ex As Exception
           Throw

       End Try

       lvItems = From filePath As String In filePaths
                 Select New ListViewItem(filePath)

       With Me.ListView1
           .BeginUpdate()
           .Items.AddRange(lvItems.ToArray)
           .EndUpdate()
       End With

   End Sub

End Class



Aunque realmente deberías utilizar el método Directory.GetFiles en lugar de usar los métodos del namespace My, el cual carece del overload para asignar múltiples extensiones, pero sigue siendo mejor, ejemplo:

Código (vbnet) [Seleccionar]
Imports System.IO

Public Class TestForm

   Private Sub TestForm_Shown() Handles MyBase.Shown

       Dim folderPath As String = "C:\"
       Dim fileExts As IEnumerable(Of String) = {"docx", "pptx"}
       Dim fInfoCol As IEnumerable(Of FileInfo)
       Dim lvItems As IEnumerable(Of ListViewItem)

       Try
           fInfoCol = GetFiles(folderPath, fileExts, SearchOption.AllDirectories)

       Catch ex As Exception
           Throw

       End Try

       lvItems = From fInfo As FileInfo In fInfoCol
                 Select New ListViewItem(fInfo.FullName)

       With Me.ListView1
           .BeginUpdate()
           .Items.AddRange(lvItems.ToArray)
           .EndUpdate()
       End With

   End Sub

   ''' <summary>
   ''' Retrieves the files inside a directory,
   ''' containing the specified file extensions.
   ''' </summary>
   ''' <param name="folderPath">The directory path where to search files.</param>
   ''' <param name="fileExts">The file extensions to match.</param>
   ''' <param name="searchOption">The searching mode.</param>
   ''' <returns>IEnumerable(Of FileInfo).</returns>
   Public Shared Function GetFiles(ByVal folderPath As String,
                                   ByVal fileExts As IEnumerable(Of String),
                                   ByVal searchOption As SearchOption) As IEnumerable(Of FileInfo)

       ' Set all the file extensions to lower-case and
       ' Remove empty file extensions and
       ' Remove "*" and "." chars from beginning of the file extension.
       fileExts = From fileExt As String In fileExts
                  Where Not String.IsNullOrEmpty(fileExt)
                  Select fileExt.TrimStart({"*"c, "."c, " "c}).TrimEnd.ToLower

       Return From filePath As String In Directory.GetFiles(folderPath, "*", searchOption)
              Where If(Not String.IsNullOrEmpty(Path.GetExtension(filePath)),
                       fileExts.Contains(Path.GetExtension(filePath).TrimStart("."c).ToLower),
                       Nothing)
              Select New FileInfo(filePath)

   End Function

End Class





Sobre el problema en cuestión, el método que te da error lo hace por causa de un desbordamiento de la pila, el motivo no lo se, no debería suceder, seguramente el caracter que has comentado esté implicado en el error al ser un caracter ilegal para una carpeta y una vulnerabilidad de la que algunos virus se aprovechan, eso es lo que puede estar ocasionando dicho desbordamiento de alguna manera, el reconocimiento de esa carpeta.

¿No puedes simplemente renombrar la carpeta a otro nombre?.

Saludos








OscarCadenas_91

#2
Hola, gracias por responder y gracias por la sugerencia de Directory.GetFiles
eh intentado probar tu codigo, pero me marca un error:
'ToArray' no es un miembro de 'System.Collections.generic.IEnumerable(Of String)'
en esta linea:
filePaths = From filePath As String In My.Computer.FileSystem.GetFiles(folderPath,
                                                                                  SearchOption.SearchAllSubDirectories,
                                                                                 fileExts.ToArray)


Solucione eso, estaba con .netframework 2 actualice a .netramework 4.5.1


Sobre lo de Renombrar el nombre de la carpeta, lo eh intentado, asì:
Código (vbnet) [Seleccionar]
 My.Computer.FileSystem.RenameDirectory("G:\" & " ", "Carpeta2")



Pero no reconoce el nombre de la carpeta y lo toma como si solo estuviese escrito "G:\"

manualmente se puede renombrar, pero desde vb.net nada, no existe alguna otra forma??



Eleкtro

#3
Cita de: OscarCadenas_91 en  3 Febrero 2015, 20:20 PM
Sobre lo de Renombrar el nombre de la carpeta, lo eh intentado, asì:
Código (vbnet) [Seleccionar]
 My.Computer.FileSystem.RenameDirectory("G:\" & " ", "Carpeta2")

Claro que no lo reconoce, estás usando un caracter de espacio, no el caracter Unicode que has comentado.

Pero a lo que me refiero es que renombres la carpeta desde el Explorer, de forma manual.
¿Porque lo quieres renombrar desde Vb.Net? (utiliza el nombre real de la carpeta para renombrarla)

saludos








OscarCadenas_91

#4
una tonteria mia, lo de no poner el valor unicode de ese caracter: "NO-BREAK SPACE" U+00A0-> (&HA0), pero igual no daba.

Lo queria hacer desde vb.net de forma automatica sin estar yendo a las propiedades del explorer,carpetas ocultas,ver la carpeta, etc, ya que cuando estaba en otras maquinas no se podia quitar los atributos de oculto y por tanto no se podia ver la carpeta en cuestion.

Encontre una forma, no se si la mejor, pero funciono:
Código (vbnet) [Seleccionar]

Shell("cmd.exe /c move /-y " & """" & "G:\" & ChrW(&HA0) & """" & " G:\Recuperado")

Ahora solo me falta hacer es que si existe esa carpeta lo cambie de nombre, caso contrario omita ese paso xD.

Gracias por la ayuda, saludos.

Eleкtro

#5
Cita de: OscarCadenas_91 en  3 Febrero 2015, 22:25 PM
Código (vbnet) [Seleccionar]

Shell("cmd.exe /c move /-y " & """" & "G:\" & ChrW(&HA0) & """" & " G:\Recuperado")

Buf...! Queda totalmente prohibido a partir de hoy utilizar Batch bajo .Net en este foro.

No, en serio, no utilices herramientas primitivas como la consola de Windows + comandos de Batch, es innecesario y no te aporta ningún control sobre dicha acción, prueba así:

Código (vbnet) [Seleccionar]
Imports System.IO

Código (vbnet) [Seleccionar]
Dim sourceFolder As String = Path.Combine("C:\", Convert.ToChar(160))
Dim destinyFolder As String = Path.Combine("C:\", "Recuperado")

Try
   Directory.CreateDirectory(sourceFolder) ' Creo la carpeta para reproducir el problema que has descrito.

   If Directory.Exists(sourceFolder) Then ' Si el directorio existe...
       ' Lo muevo.
       Directory.Move(sourceFolder, destinyFolder)
   End If

Catch ex As Exception
   Throw

End Try


saludos








OscarCadenas_91

#6
gracias por todo, aun me falta mucho por aprender.

Sobre lo de intentar reproducir el problema con:

Código (vbnet) [Seleccionar]
Directory.CreateDirectory(sourceFolder)

No crea el directorio con ese caracter y tambien lo de si existe esa ruta tampoco funciona(supongo que debe ser por ese caracter).

Lo que si funciona es:
Código (vbnet) [Seleccionar]
Directory.Move(sourceFolder, DestinyFolder)

Ya estaba pensando en usar el "On Error Resume Next", pero decidi hacerlo asi:

Código (vbnet) [Seleccionar]

  Private Sub TestForm_Shown() Handles MyBase.Shown
       Dim sourceFolder As String = Path.Combine("G:\", Convert.ToChar(160))
       Dim DestinyFolder As String = Path.Combine("G:\", "Recuperado")
       Try
           Directory.Move(sourceFolder, DestinyFolder)
       Catch ex As Exception

       Finally
           Dim folderPath As String = "G:\"
           Dim fileExts As IEnumerable(Of String) = {"docx", "pptx"}
           Dim fInfoCol As IEnumerable(Of FileInfo)
           Dim lvItems As IEnumerable(Of ListViewItem)

           Try
               fInfoCol = GetFiles(folderPath, fileExts, SearchOption.AllDirectories)

           Catch ex As Exception
               Throw

           End Try

           lvItems = From fInfo As FileInfo In fInfoCol
                     Select New ListViewItem(fInfo.FullName)

           With Me.ListView1
               .BeginUpdate()
               .Items.AddRange(lvItems.ToArray)
               .EndUpdate()
           End With
       End Try
   End Sub

   ''' <summary>
   ''' Retrieves the files inside a directory,
   ''' containing the specified file extensions.
   ''' </summary>
   ''' <param name="folderPath">The directory path where to search files.</param>
   ''' <param name="fileExts">The file extensions to match.</param>
   ''' <param name="searchOption">The searching mode.</param>
   ''' <returns>IEnumerable(Of FileInfo).</returns>
   Public Shared Function GetFiles(ByVal folderPath As String,
                                   ByVal fileExts As IEnumerable(Of String),
                                   ByVal searchOption As SearchOption) As IEnumerable(Of FileInfo)

       ' Set all the file extensions to lower-case and
       ' Remove empty file extensions and
       ' Remove "*" and "." chars from beginning of the file extension.
       fileExts = From fileExt As String In fileExts
                  Where Not String.IsNullOrEmpty(fileExt)
                  Select fileExt.TrimStart({"*"c, "."c, " "c}).TrimEnd.ToLower

       Return From filePath As String In Directory.GetFiles(folderPath, "*", searchOption)
              Where If(Not String.IsNullOrEmpty(Path.GetExtension(filePath)),
                       fileExts.Contains(Path.GetExtension(filePath).TrimStart("."c).ToLower),
                       Nothing)
              Select New FileInfo(filePath)

   End Function


Asi me funciona, si sigo estoy equivocado corrigeme

Saludos




Eleкtro

#7
Cita de: OscarCadenas_91 en  4 Febrero 2015, 06:13 AMNo crea el directorio con ese caracter y tambien lo de si existe esa ruta tampoco funciona(supongo que debe ser por ese caracter).

En mi caso si que me crea correctamente la carpeta con dicho caracter, no se me ocurre porque motivo a ti no funciona. ¿la instrucción no lanza ninguna excepción?, en caso afirmativo, ¿cual es el mensaje de error y el stack trace?.




Cita de: OscarCadenas_91 en  4 Febrero 2015, 06:13 AMAsi me funciona, si sigo estoy equivocado corrigeme

Hombre, un bloque try/catch anidado dentro de un bloque finally no es muy buena idea, el bloque finally contiene el código que será evaluado en todas las condiciones ocurra o no ocurra una excepción, puedes utilizarlo como un "On Error Resume Next", pero el bloque finally no se suele usar con la finalidad que le estás dando, sino más bien para hacer una limpieza, un cleanup, por ejemplo para asegurarse de liberar los recursos usados por objetos disposables:

Código (vbnet) [Seleccionar]
' Un objeto disposable cualquiera.
Dim obj As MemoryStream

Try
   ' Instancio la class disposable.
   obj = New MemoryStream
   ' Intento leer un bloque de bytes en un buffer vacío, dará error.
   obj.Read(New Byte() {}, 0, 1)
   ' Las instrucciones de abajo no se procesarán ya que terminó la ejecución de este bloque debido al error.
   obj.Flush()
   obj.Close()

Catch ex As Exception
   ' Controlar la excepción.
   MsgBox(ex.Message)

Finally
   ' Asegurarse de liberar los recursos del objeto, se haya controlado o no la excepción.
   If obj IsNot Nothing Then
       obj.Flush()
       obj.Close()
   End If

End Try


El código que has mostrado, yo lo dejaría así:
EDITO: Bueno, también debo decir que la función GetFiles como ves devuelve una colección de objetos FileInfo, si no necesitas ningún dato más que la ruta del archivo entonces se puede simplificar bastante más para evitar algunas sentencias de LINQ innecesarias.

Código (vbnet) [Seleccionar]
       Dim folderPath As String = "G:\"
       Dim sourceFolder As String = Path.Combine(folderPath, Convert.ToChar(160))
       Dim destinyFolder As String = Path.Combine(folderPath, "Recuperado")
       Dim fileExts As IEnumerable(Of String) = {"docx", "pptx"}
       Dim fInfoCol As IEnumerable(Of FileInfo)
       Dim lvItems As ListViewItem()

       Try
           Directory.Move(sourceFolder, destinyFolder)
       Catch ' Omito cualquier excepción.
       End Try

       Try
           fInfoCol = GetFiles(folderPath, fileExts, SearchOption.AllDirectories)
       Catch ' Omito cualquier excepción.
       End Try

       lvItems = (From fInfo As FileInfo In fInfoCol
                  Select New ListViewItem(fInfo.FullName)).ToArray

       With Me.ListView1
           .BeginUpdate()
           .Items.AddRange(lvItems)
           .EndUpdate()
       End With

   ''' <summary>
  ''' Retrieves the files inside a directory,
  ''' containing the specified file extensions.
  ''' </summary>
  ''' <param name="folderPath">The directory path where to search files.</param>
  ''' <param name="fileExts">The file extensions to match.</param>
  ''' <param name="searchOption">The searching mode.</param>
  ''' <returns>IEnumerable(Of FileInfo).</returns>
  Public Shared Function GetFiles(ByVal folderPath As String,
                                  ByVal fileExts As IEnumerable(Of String),
                                  ByVal searchOption As SearchOption) As IEnumerable(Of FileInfo)

      ' Set all the file extensions to lower-case and
      ' Remove empty file extensions and
      ' Remove "*" and "." chars from beginning of the file extension.
      fileExts = From fileExt As String In fileExts
                 Where Not String.IsNullOrEmpty(fileExt)
                 Select fileExt.TrimStart({"*"c, "."c, " "c}).TrimEnd.ToLower

      Return From filePath As String In Directory.GetFiles(folderPath, "*", searchOption)
             Where If(Not String.IsNullOrEmpty(Path.GetExtension(filePath)),
                      fileExts.Contains(Path.GetExtension(filePath).TrimStart("."c).ToLower),
                      Nothing)
             Select New FileInfo(filePath)

  End Function


saludos








OscarCadenas_91

Ok guardado todo lo que me dices, sobre lo de finally.  :P

sobre lo de crear esa carpeta, sin colocarlo en un bloque try/catch, abre y se cierra.
Bajo el bloque Try/Catch, me manda este error:

Excepción:Se produjo: "No se puede encontrar una parte de la ruta de acceso 'G:\'." (System.IO.DirectoryNotFoundException)
Se produjo una System.IO.DirectoryNotFoundException: "No se puede encontrar una parte de la ruta de acceso 'G:\'."


Mi USB esta formateado en Fat32, en un disco duro formateado en NTFS no muestra error ni tampoco se cierra.

Eleкtro

Quizás esto te pueda ayudar, porque yo no dispongo ahora mismo de ninguna partición FAT32 para probar los nombres:
http://stackoverflow.com/questions/19503697/unicode-filenames-on-fat-32

¿Como solucionarlo?, ...pues sinceramente, a parte de darle un formato NTFS al dispositivo USB, ni idea.

Saludos