Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: Eleкtro en 18 Enero 2013, 10:10 am



Título: [SOLUCIONADO] Una pregunta sobre IO.Directory.GetFiles
Publicado por: Eleкtro en 18 Enero 2013, 10:10 am
¿No se puede usar algún separador de expresión?

He intentado esto:

Código
  1. IO.Directory.GetFiles(Directory, "*.exe, *.vb")
  2.  
  3. IO.Directory.GetFiles(Directory, "*.exe; *.vb")
  4.  
  5. IO.Directory.GetFiles(Directory, "*.exe" + "*.vb")
  6.  
  7. IO.Directory.GetFiles(Directory, "*.exe" + IO.Path.AltDirectorySeparatorChar + "*.vb")
  8.  
  9. IO.Directory.GetFiles(Directory, "*.exe" + IO.Path.DirectorySeparatorChar + "*.vb")


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: Novlucker en 18 Enero 2013, 12:15 pm
Hasta donde se no :-\ Puedes obtener todos los resultados y filtrar, o bien puedes buscar varias veces, pero no directamente :-\

Saludos


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: 3mp3z@ndo en 18 Enero 2013, 12:30 pm
Tal vez te sirva esto:

http://stackoverflow.com/questions/163162/can-you-call-directory-getfiles-with-multiple-filters (http://stackoverflow.com/questions/163162/can-you-call-directory-getfiles-with-multiple-filters)

Un saludo


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: Eleкtro en 18 Enero 2013, 13:17 pm
Puf, para perder tiempo de lectura de disco haciendo múltiples búsquedas y/o filtrando la lista... busco algo más "natural"
creo que jamás diría esto, pero es que para eso es mejor usar el comando "DIR" de la CMD (en VB.NET) sincéramente xD.

@3mp3z@ndo
Gracias por la info , parece la mejor opción pero me queda la duda,

¿Esto solo hace una búsqueda y filtra, o hace dos búsquedas?
Código
  1. Dim files = Directory.GetFiles("C:\", "*").Where(Function(s) s.EndsWith(".exe") OrElse s.EndsWith(".xml"))


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: Novlucker en 18 Enero 2013, 13:25 pm
¿Esto solo hace una búsqueda y filtra, o hace dos búsquedas?
Código
  1. Dim files = Directory.GetFiles("C:\", "*").Where(Function(s) s.EndsWith(".exe") OrElse s.EndsWith(".xml"))
Primero listas todos los archivos (*.*) y luego filtras en memoria

Saludos


Título: Re: [SOLUCIONADO] Una pregunta sobre IO.Directory.GetFiles
Publicado por: Eleкtro en 26 Enero 2013, 15:42 pm
Como se podría optimizar el código para crear una función de esto?

Por ejemplo:

Código
  1.    Private Sub Form1_Load()
  2.        Dim File_Extensions() As String = {"*.txt", "*.ini", "*.exe", "*.pdf"}
  3.        Dim Files() = Get_Files_By_FileExtensions("C:\", File_Extensions)
  4.    End Sub

Y entonces aquí se debería agregar automáticamente un "orelse s.EndsWith(siguiente extensión)" por cada extensión de la colección:
Código
  1.    Public Function Get_Files_By_FileExtensions(ByVal Directory As String, ByVal Extensions() As String) As System.IO.FileInfo()
  2.        Return IO.Directory.GetFiles(Directory, "*").Where(Function(s) s.EndsWith(Extensions(0)) _
  3.        OrElse s.EndsWith(Extensions(1)) _
  4.        OrElse s.EndsWith(Extensions(2)) _
  5.        OrElse s.EndsWith(Extensions(3)))
  6.    End Function

¿Es posible hacerlo?


EDITO: Yo ya tengo funciones para listar archivos, pero preciso hacerlo con ese código que menciono (me resulta más limpio porque sólo hace una búsqueda)


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: _katze_ en 26 Enero 2013, 18:18 pm
si quieres algo rapido y optimo, usas apis, regular expresion,


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: Eleкtro en 26 Enero 2013, 19:54 pm
si quieres algo rapido y optimo, usas apis, regular expresion,

Gracias, pero podrías indicarme (para buscar info) con que API y que función _katze_?


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: _katze_ en 27 Enero 2013, 12:59 pm
codigo vieejo y con ayuda de varias, pero la connserve y justo t viene para aprender

Código
  1. Imports System.Runtime.InteropServices
  2. Imports System.Text.RegularExpressions
  3. Imports System.Text
  4. Imports System.IO
  5.  
  6. Public Class ClsBucarFiles
  7.  
  8. #Region "   Icon    "
  9.  
  10.    Private Structure SHFILEINFO
  11.        Public hIcon As IntPtr ' : icon
  12.        Public iIcon As Integer ' : icondex
  13.        Public dwAttributes As Integer ' : SFGAO_ flags
  14.        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
  15.        Public szDisplayName As String
  16.        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
  17.        Public szTypeName As String
  18.    End Structure
  19.  
  20.    Private Declare Ansi Function SHGetFileInfo Lib "shell32.dll" (ByVal pszPath As String, _
  21.    ByVal dwFileAttributes As Integer, ByRef psfi As SHFILEINFO, ByVal cbFileInfo As Integer, _
  22.    ByVal uFlags As Integer) As IntPtr
  23.  
  24.    Private Const SHGFI_SMALLICON As Long = &H1
  25.    Private Const SHGFI_SYSICONINDEX As Long = &H4000
  26.    Private Const SHGFI_USEFILEATTRIBUTES As Long = &H10
  27.    Private Const SHGFI_TYPENAME As Long = &H400
  28.    Private Const SHGFI_DISPLAYNAME As Long = &H200
  29.    Private Const SHGFI_ICON = &H100
  30.    Private Const SHGFI_LARGEICON = &H0         ' Large icon
  31.    Private Shared shfitmp As SHFILEINFO   'just used for the following
  32.    Private Shared SHFILESIZE As Integer = Marshal.SizeOf(shfitmp.GetType())
  33.  
  34.    Public Function ptricon(ByVal vsPath As String) As IntPtr
  35.        Dim hImgSmall As IntPtr
  36.        Dim shinfo As New SHFILEINFO()
  37.        shinfo.szDisplayName = New String(Chr(0), 260)
  38.        shinfo.szTypeName = New String(Chr(0), 80)
  39.        hImgSmall = SHGetFileInfo(vsPath, 0&, shinfo, SHFILESIZE, _
  40.        SHGFI_ICON Or SHGFI_SYSICONINDEX Or SHGFI_SMALLICON)
  41.        Return (shinfo.hIcon)
  42.    End Function
  43.  
  44. #End Region
  45.  
  46. #Region " Declaraciones "
  47.    <DllImport("kernel32.dll")> _
  48.    Private Shared Function FindClose(ByVal hFindFile As IntPtr) As Boolean
  49.    End Function
  50.  
  51.    <DllImport("kernel32.dll", CharSet:=CharSet.None)> _
  52.    Private Shared Function FindFirstFile(ByVal lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As IntPtr
  53.    End Function
  54.  
  55.    Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As IntPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As Boolean
  56.  
  57.    <StructLayout(LayoutKind.Sequential)> _
  58.    Structure WIN32_FIND_DATA
  59.        Public dwFileAttributes As UInteger
  60.        Public ftCreationTime As System.Runtime.InteropServices.ComTypes.FILETIME
  61.        Public ftLastAccessTime As System.Runtime.InteropServices.ComTypes.FILETIME
  62.        Public ftLastWriteTime As System.Runtime.InteropServices.ComTypes.FILETIME
  63.        Public nFileSizeHigh As UInteger
  64.        Public nFileSizeLow As UInteger
  65.        Public dwReserved0 As UInteger
  66.        Public dwReserved1 As UInteger
  67.        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> Public cFileName As String
  68.        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> Public cAlternateFileName As String
  69.    End Structure
  70.  
  71.  
  72.    Public Event FileFound(ByVal sPath As String, ByVal sFile As String, ByVal atributos As FileAttributes)
  73.    Public Event FolderFound(ByVal sPath As String, ByVal sFolder As String, ByVal atributos As FileAttributes)
  74.  
  75.    Private cancel As Boolean = False
  76.  
  77.    Private INVALID_HANDLE_VALUE As New IntPtr(-1)
  78.  
  79.    Private RegExp As Regex
  80.  
  81.    Private sbFiles As New StringBuilder
  82.  
  83.    Private sbFolders As New StringBuilder
  84. #End Region
  85.  
  86. #Region " PRocedimientos "
  87.  
  88.    Public Sub New()
  89.  
  90.        MyBase.New()
  91.    End Sub
  92.  
  93.    Public Sub start()
  94.        If RegExp Is Nothing Then
  95.            RegExp = New Regex(p_match, RegexOptions.IgnoreCase)
  96.        Else
  97.            RegExp = Nothing
  98.            RegExp = New Regex(p_match, RegexOptions.IgnoreCase)
  99.        End If
  100.  
  101.        cancel = False
  102.  
  103.        Dim arrdrive() As String
  104.  
  105.        arrdrive = p_path.Split(Chr(59))
  106.  
  107.        For Each s As String In arrdrive
  108.            Call SubBusqueda(s) 'recursividad xD
  109.        Next
  110.  
  111.    End Sub
  112.  
  113.    Public Sub Cancelar()
  114.        cancel = True
  115.    End Sub
  116.    Private Function StripNulls(ByVal sData As String) As String
  117.        StripNulls = Left$(sData, Len(sData))
  118.    End Function
  119.    Private Sub SubBusqueda(ByVal vsPath As String)
  120.        Dim ptrSearch As New IntPtr
  121.        Dim vsfile As String = String.Empty
  122.        Dim vsfolder As String = String.Empty
  123.        Dim vaDir As New ArrayList
  124.        Dim wfd As New WIN32_FIND_DATA
  125.        Dim dir As String = String.Empty
  126.        Dim ret As Boolean
  127.  
  128.        If cancel Then Exit Sub
  129.  
  130.        Call NormalizePath(vsPath)
  131.        ptrSearch = FindFirstFile(vsPath & "*", wfd)
  132.  
  133.        If Not ptrSearch = INVALID_HANDLE_VALUE Then
  134.  
  135.            Do
  136.                If (wfd.dwFileAttributes And FileAttributes.Directory) <> FileAttributes.Directory Then
  137.                    vsfile = StripNulls(wfd.cFileName)
  138.  
  139.                    If Not p_hide Then
  140.  
  141.                        If (wfd.dwFileAttributes And FileAttributes.Hidden) = FileAttributes.Hidden Then GoTo FNEXT
  142.  
  143.                    End If
  144.  
  145.                    If RegExp.Matches(vsfile).Count = 0 Then GoTo FNEXT
  146.  
  147.                    sbFiles.AppendLine(vsfile)
  148.  
  149.                    RaiseEvent FileFound(vsPath, vsfile, CType(wfd.dwFileAttributes, FileAttributes))
  150.                Else
  151.  
  152.                    If Not p_hide Then
  153.                        If (wfd.dwFileAttributes And FileAttributes.Hidden) = FileAttributes.Hidden Then GoTo FNEXT
  154.                    End If
  155.  
  156.                    vsfolder = StripNulls(wfd.cFileName)
  157.  
  158.                    If (vsfolder <> ".") And (vsfolder <> "..") Then
  159.                        dir = vsPath & vsfolder & "\"
  160.  
  161.                        If Not p_sys Then
  162.  
  163.                            If dir = Environ("Windir") & "\" Then GoTo FNEXT
  164.                        End If
  165.  
  166.                        vaDir.Add(dir)
  167.                        If RegExp.Matches(vsfolder).Count = 0 Then GoTo FNEXT
  168.                        sbFolders.AppendLine(vsfolder)
  169.                        RaiseEvent FolderFound(vsPath, vsfolder, CType(wfd.dwFileAttributes, FileAttributes))
  170.  
  171.                    End If
  172.                End If
  173. FNEXT:
  174.  
  175.                If cancel Then FindClose(ptrSearch) : Exit Sub
  176.                Application.DoEvents()
  177.  
  178.                ret = FindNextFile(ptrSearch, wfd)
  179.            Loop While ret
  180.            Call FindClose(ptrSearch)
  181.        End If
  182.  
  183.        If p_subfolder Then
  184.  
  185.            For i As Integer = 0 To vaDir.Count - 1
  186.  
  187.                Call SubBusqueda(CStr(vaDir(i)))
  188.            Next
  189.  
  190.        End If
  191.    End Sub
  192.  
  193.    Private Function drivers() As String
  194.        Dim drive As DriveInfo
  195.        Dim dr As New StringBuilder
  196.  
  197.        For Each drive In DriveInfo.GetDrives
  198.            With drive
  199.                If .IsReady Then
  200.                    dr.Append(drive.Name & ";")
  201.                End If
  202.            End With
  203.        Next
  204.        Return dr.ToString
  205.    End Function
  206.  
  207.    Private Function ReplaceFilter(ByVal sFilter As String) As String
  208.        sFilter = sFilter.Replace("+", "\+")
  209.        sFilter = sFilter.Replace(".", "\.")
  210.        sFilter = sFilter.Replace("|", "\|")
  211.        sFilter = sFilter.Replace(";", "|\b")
  212.        sFilter = sFilter.Replace(" ", "|\b")
  213.        sFilter = sFilter.Replace("{", "\{")
  214.        sFilter = sFilter.Replace("}", "\}")
  215.        sFilter = sFilter.Replace("*", ".+")
  216.        sFilter = sFilter.Replace("?", ".{1}")
  217.        sFilter = sFilter.Replace("(", "\(")
  218.        sFilter = sFilter.Replace(")", "\)")
  219.        sFilter = sFilter.Replace("^", "\^")
  220.        sFilter = sFilter.Replace("$", "\$")
  221.        sFilter = sFilter.Replace("[", "\[")
  222.        sFilter = sFilter.Replace("[", "\]")
  223.  
  224.        Do While CBool(InStr(sFilter, "|\b|\b"))
  225.            sFilter = Replace$(sFilter, "|\b|\b", "|\b")
  226.        Loop
  227.        Return "^(" & sFilter & ")$|(" & sFilter & ".+)"
  228.    End Function
  229.  
  230.  
  231.    Public Function NormalizePath(byval sData As String) As String
  232.  
  233.        If Strings.Len(sData) > 1 Then
  234.            sData = Strings.Replace(sData, "/", "\")
  235.            If Not Strings.Right(sData, 1) = "\" Then
  236.                Return sData & "\"
  237.            Else
  238.                Return sData
  239.            End If
  240.        End If
  241.  
  242.    End Function
  243.  
  244.  
  245. #End Region
  246.  
  247. #Region " propiedades "
  248.    Private p_match As String = String.Empty
  249.  
  250.    WriteOnly Property Match() As String
  251.        Set(ByVal value As String)
  252.            p_match = ReplaceFilter(value)
  253.        End Set
  254.    End Property
  255.  
  256.    Private p_subfolder As Boolean = False
  257.    Property SubFolder() As Boolean
  258.        Get
  259.            Return p_subfolder
  260.        End Get
  261.        Set(ByVal value As Boolean)
  262.            p_subfolder = value
  263.        End Set
  264.    End Property
  265.    Private p_hide As Boolean = False
  266.    Property HideFolder() As Boolean
  267.        Get
  268.            Return p_hide
  269.        End Get
  270.        Set(ByVal value As Boolean)
  271.            p_hide = value
  272.        End Set
  273.    End Property
  274.    Private p_sys As Boolean = False
  275.    Property SysFolder() As Boolean
  276.        Get
  277.            Return p_sys
  278.        End Get
  279.        Set(ByVal value As Boolean)
  280.            p_sys = value
  281.        End Set
  282.    End Property
  283.    Private p_path As String = drivers()
  284.    Property Path() As String
  285.        Get
  286.            Return p_path
  287.        End Get
  288.        Set(ByVal value As String)
  289.  
  290.            p_path = NormalizePath(value)
  291.        End Set
  292.    End Property
  293.    ReadOnly Property FilesString() As String
  294.        Get
  295.            Return sbFolders.ToString
  296.        End Get
  297.    End Property
  298.  
  299.    ReadOnly Property FolderString() As String
  300.        Get
  301.  
  302.            Return sbFolders.ToString
  303.        End Get
  304.    End Property
  305. #End Region
  306.  
  307. End Class
  308.  


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: Novlucker en 27 Enero 2013, 23:09 pm
El código no está mal pero ... si miras el código interno de IO.Directory.GetFiles verás que hace uso de la siguiente clase, y de las mismas API
Código
  1. <Serializable, StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto), BestFitMapping(False)> _
  2. Friend Class WIN32_FIND_DATA
  3.    Friend dwFileAttributes As Integer
  4.    Friend ftCreationTime_dwLowDateTime As UInt32
  5.    Friend ftCreationTime_dwHighDateTime As UInt32
  6.    Friend ftLastAccessTime_dwLowDateTime As UInt32
  7.    Friend ftLastAccessTime_dwHighDateTime As UInt32
  8.    Friend ftLastWriteTime_dwLowDateTime As UInt32
  9.    Friend ftLastWriteTime_dwHighDateTime As UInt32
  10.    Friend nFileSizeHigh As Integer
  11.    Friend nFileSizeLow As Integer
  12.    Friend dwReserved0 As Integer
  13.    Friend dwReserved1 As Integer
  14.    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
  15.    Friend cFileName As String
  16.    <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> _
  17.    Friend cAlternateFileName As String
  18.    <TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")> _
  19.    Public Sub New()
  20. End Class

Saludos :P


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: _katze_ en 27 Enero 2013, 23:51 pm
pero al hacerlo con mi clase no necesits permisos de administrador ni ninguna magia negra. como con el frame :-*


Título: Re: Una pregunta sobre IO.Directory.GetFiles
Publicado por: Eleкtro en 9 Junio 2013, 09:07 am
A pesar de la bonita Class de _katze_ (por cierto, gracias), y después de mucho buscar la manera más óptima ...al final me quedo con esta función:

Código
  1. Private Function Get_Files(ByVal Path As String, ParamArray exts() As String) As List(Of IO.FileInfo)
  2.    Return New IO.DirectoryInfo(Path).GetFiles.Where(Function(o) exts.Contains(o.Extension)).ToList
  3. End Function

Código
  1. For Each file In Get_Files("C:\Windows", {".dll", ".ini"}) : MsgBox(file.Name) : Next

Más sencillo y eficaz creo que sería imposible!

Lo malo es que no se me ocurre como hacer para que la función me permita buscar de manera recursiva,
me gustaría poder implementar la recursividad en esa función, preservando su maravillosa sencillez, elegancia y eficacia, es decir...que no quiero llenar la función de Fors para hacer largos recorridos en los subdirectorios estropeando la performance de la función.

¿Alguien tiene idea de que modificaciones necesita la función para hacerla recursiva?


Título: Re: [SOLUCIONADO] Una pregunta sobre IO.Directory.GetFiles
Publicado por: Eleкtro en 10 Junio 2013, 20:13 pm
Ahora sí, mejor imposible!, aquí tienen la forma más eficiente:

Código
  1.    Private Function Get_Files(ByVal rootDirectory As String, ByVal recursive As Boolean, ParamArray exts() As String) As List(Of IO.FileInfo)
  2.        Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
  3.        Return IO.Directory.GetFiles(rootDirectory, "*.*", searchOpt).Where(Function(o) exts.Contains(IO.Path.GetExtension(o))).Select(Function(p) New IO.FileInfo(p)).ToList
  4.    End Function

Ejemplo de uso:

Código
  1.    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  2.        For Each file In Get_Files("C:\Windows", True, {".dll", "DLL"}) : MsgBox(file.Name) : Next
  3.    End Sub

EDITO: Lo único imperfecto es que no es Ignore case, así que habría que usar la función así:
Código
  1. For Each file In Get_Files("C:\Windows", True, {".dll", "DLL"}) : MsgBox(file.Name) : Next

 ;D