From HashVB
Jump to: navigation, search


FindFirstFile is an API which allows the navigation through a computer's file system directly without relying on the FileSystemObject or VB's file system functions. Used in conjunction with FindNextFile, one can easily navigate an entire drive recursively. Requires WIN32_FIND_DATA type and FILETIME type


Both APIs exist in ANSI and Unicode form. These declarations are the Unicode versions. For ANSI, simply replace the "W" suffix with an "A" and change the first parameter's type to string.

  Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileW" (ByVal lpFileName As Long, lpFindFileData As WIN32_FIND_DATA) As Long
  Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileW" (ByVal hFindFile As Long, lpFindFileData As    WIN32_FIND_DATA) As Long
  Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
  Private Const INVALID_FILE_ATTRIBUTES As Long = -1&
  Private Const INVALID_HANDLE_VALUE As Long = -1&
  Private Const MAX_PATH As Long = 260


  Private Type FILETIME
     dwLowDateTime As Long
     dwHighDateTime As Long
  End Type
  Private Type WIN32_FIND_DATA        
     dwFileAttributes As Long         
     ftCreationTime As FILETIME
     ftLastAccessTime As FILETIME
     ftLastWriteTime As FILETIME
     nFileSizeHigh As Long
     nFileSizeLow As Long
     dwReserved0 As Long
     dwReserved1 As Long
     cFileName(0 To (MAX_PATH * 2) - 1) As Byte 
     cAlternate(0 To 27) As Byte                
  End Type

Example Code

  Private Sub DirW(ByVal SearchPath As String)
     Dim hFind As Long, WFD As WIN32_FIND_DATA, sFile as String, sTemp as String
     ' Remove trailing slash, just in case.  For concatenation later
     If Right$(SearchPath, 1) = "\" Then SearchPath = Left$(SearchPath, Len(SearchPath) - 1)    
     ' Prepend necessary long/UNC identifier and append trailing wildcards.
     If Left$(SearchPath, 2) = "\\" Then
        SearchPath = "\\?\UNC\" & Mid$(SearchPath, 3) & "\*.*"
        SearchPath = "\\?\" & SearchPath & "\*.*"
     End If
     hFind = FindFirstFile(StrPtr(SearchPath), WFD)
     If hFind <> INVALID_HANDLE_VALUE Then
           sTemp = TrimNull(WFD.cFileName)
           If sTemp <> "." And sTemp <> ".." Then
               If Right$(sFile , 1) <> "\" Then sFile = sFile & "\"
               ' .dwFileAttributes holds a numerical value representing
               ' whether the file/directory has certain attributes.
               ' 16, 17, 48, 49, 8208, 8209, 8214, and 8215 are directories
               Select Case WFD.dwFileAttributes
                   Case 16, 17, 48, 49, 8208, 8209, 8214, 8215
                       ' These are directories
                       ' Add whatever code here
                       Call DirW(sFile & temP, temP2)        ' recurse through this dir
                   Case 22                                   ' Don't recurse on these directories, or it'll crash
                       GoTo skip  
                   Case Else                        
                       ' These are files
                       ' Add whatever code here
               End Select
           End If
        Loop Until FindNextFile(hFind, WFD) = 0
     End If
     Call FindClose(hFind)   ' Clean up.
  End Function
  Private Function TrimNull(ByVal Data As String) As String
     Dim nNull As Long
     nNull = InStr(Data, vbNullChar)
     Select Case nNull
        Case 0  ' Just do normal trim
           TrimNull = Trim$(Data)
        Case 1  ' Empty string
           TrimNull = ""
        Case Else
           TrimNull = Left$(Data, nNull - 1)
     End Select
  End Function