Results 1 to 3 of 3

Thread: FindFirstFileEx

  1. #1
    Join Date
    Jan 2004

    Unanswered: FindFirstFileEx

    I have an Access 97 database running on windows 2000. What the database does is recursively calls a fuction which basically scans the hard drive or network drive looking for a particular file type. At the moment the code uses the API FindFirstFile to find all the sub directories in a given directory. This is done by cycling through the returned results one by one which includes every file in that directory. Then the function does another search on same directory for the specified file type. This seems a little tedious to me especially cause there could be about 2500 files in a directory and only 2 sub directories and the code has to cycle through every single one of them.

    Does anybody know how to use the function FindFirstFileEx. I want to be able to only return the sub directories in the first part of the function. I can't seem to find any examples for it in VB on the net, only in C and C++, and I know nothing about C and therefore cannot translate it. I have found the declaration in VB but that is about it.

    Any help in this matter would be greatly appreciated.

  2. #2
    Join Date
    Nov 2003
    From: API-Guide 3.7

    The FindFirstFile function searches a directory for a file whose name matches the specified filename. FindFirstFile examines subdirectory names as well as filenames.


    · lpFileName
    Windows 95: Points to a null-terminated string that specifies a valid directory or path and filename, which can contain wildcard characters (* and ?). This string must not exceed MAX_PATH characters.

    Windows NT: Points to a null-terminated string that specifies a valid directory or path and filename, which can contain wildcard characters (* and ?).

    There is a default string size limit for paths of MAX_PATH characters. This limit is related to how the FindFirstFile function parses paths. An application can transcend this limit and send in paths longer than MAX_PATH characters by calling the wide (W) version of FindFirstFile and prepending “\\?\” to the path. The “\\?\” tells the function to turn off path parsing; it lets paths longer than MAX_PATH be used with FindFirstFileW. This also works with UNC names. The “\\?\” is ignored as part of the path. For example, “\\?\C:\myworld\private” is seen as “C:\myworld\private”, and “\\?\UNC\bill_g_1\hotstuff\coolapps” is seen as “\\bill_g_1\hotstuff\coolapps”.

    · lpFindFileData
    Points to the WIN32_FIND_DATA structure that receives information about the found file or subdirectory. The structure can be used in subsequent calls to the FindNextFile or FindClose function to refer to the file or subdirectory.

    'Create a form with a command button (command1), a list box (list1)
    'and four text boxes (text1, text2, text3 and text4).
    'Type in the first textbox a startingpath like c:\
    'and in the second textbox you put a pattern like *.* or *.txt
    Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, _
    lpFindFileData As WIN32_FIND_DATA) As Long
    Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, _
    lpFindFileData As WIN32_FIND_DATA) As Long
    Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
    Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
    Const MAX_PATH = 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 As String * MAX_PATH
        cAlternate As String * 14
    End Type
    Function StripNulls(OriginalStr As String) As String
        If (InStr(OriginalStr, Chr(0)) > 0) Then
            OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
        End If
        StripNulls = OriginalStr
    End Function
    Function FindFilesAPI(path As String, SearchStr As String, FileCount As Integer, DirCount As Integer)
        Dim FileName As String ' Walking filename variable...
        Dim DirName As String ' SubDirectory Name
        Dim dirNames() As String ' Buffer for directory name entries
        Dim nDir As Integer ' Number of directories in this path
        Dim i As Integer ' For-loop counter...
        Dim hSearch As Long ' Search Handle
        Dim WFD As WIN32_FIND_DATA
        Dim Cont As Integer
        If Right(path, 1) <> "\" Then path = path & "\"
        ' Search for subdirectories.
        nDir = 0
        ReDim dirNames(nDir)
        Cont = True
        hSearch = FindFirstFile(path & "*", WFD)
        If hSearch <> INVALID_HANDLE_VALUE Then
            Do While Cont
            DirName = StripNulls(WFD.cFileName)
            ' Ignore the current and encompassing directories.
            If (DirName <> ".") And (DirName <> "..") Then
                ' Check for directory with bitwise comparison.
                If GetFileAttributes(path & DirName) And FILE_ATTRIBUTE_DIRECTORY Then
                    dirNames(nDir) = DirName
                    DirCount = DirCount + 1
                    nDir = nDir + 1
                    ReDim Preserve dirNames(nDir)
                End If
            End If
            Cont = FindNextFile(hSearch, WFD) 'Get next subdirectory.
            Cont = FindClose(hSearch)
        End If
        ' Walk through this directory and sum file sizes.
        hSearch = FindFirstFile(path & SearchStr, WFD)
        Cont = True
        If hSearch <> INVALID_HANDLE_VALUE Then
            While Cont
                FileName = StripNulls(WFD.cFileName)
                If (FileName <> ".") And (FileName <> "..") Then
                    FindFilesAPI = FindFilesAPI + (WFD.nFileSizeHigh * MAXDWORD) + WFD.nFileSizeLow
                    FileCount = FileCount + 1
                    List1.AddItem path & FileName
                End If
                Cont = FindNextFile(hSearch, WFD) ' Get next file
            Cont = FindClose(hSearch)
        End If
        ' If there are sub-directories...
        If nDir > 0 Then
            ' Recursively walk into them...
            For i = 0 To nDir - 1
                FindFilesAPI = FindFilesAPI + FindFilesAPI(path & dirNames(i) & "\", SearchStr, FileCount, DirCount)
            Next i
        End If
    End Function
    Sub Command1_Click()
        Dim SearchPath As String, FindStr As String
        Dim FileSize As Long
        Dim NumFiles As Integer, NumDirs As Integer
        Screen.MousePointer = vbHourglass
        SearchPath = Text1.Text
        FindStr = Text2.Text
        FileSize = FindFilesAPI(SearchPath, FindStr, NumFiles, NumDirs)
        Text3.Text = NumFiles & " Files found in " & NumDirs + 1 & " Directories"
        Text4.Text = "Size of files found under " & SearchPath & " = " & Format(FileSize, "#,###,###,##0") & " Bytes"
        Screen.MousePointer = vbDefault
    End Sub
    Hope this sheds a little light on the subject.....

    Make this easier to read Uncle Bob.

  3. #3
    Join Date
    Jan 2004
    Thanks for you reply.

    I have already got FindFirstFile working in the same way that is listed in your example. I want to get FindFirstFileEx to work in replace of FindFirstFile. That way I can get it to return directories only, instead of having to walk through each returned item and check to see if it is a directory or not.

    FindFirstFile is becoming to be a performance issue, by cycling through thousands of files when I only need two directories. I am hoping that FindFirstFileEx will alleviate this problem by only returning the two directories that I want.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts