CodeItBetter Programming Another VB Programming Blog

How to scan folders for Files (in two ways)

Posted on January 5, 2009
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
'File/Folder Handling - How to scan folders for Files (in two ways)
'Method 1

'Place a command button and a list box on a form

Option Explicit
 
Dim FSys As FileSystemObject
 
'Constant Value Description for FileAttributes

'Normal     0 Normal file. No attributes are set.
'ReadOnly   1 Read-only file. Attribute is read/write.
'Hidden     2 Hidden file. Attribute is read/write.
'System     4 System file. Attribute is read/write.
'Volume     8 Disk drive volume label. Attribute is read-only.
'Directory  16 Folder or directory. Attribute is read-only.
'Archive    32 File has changed since last backup. Attribute is read/write.
'Alias      64 Link or shortcut. Attribute is read-only.
'Compressed 128 Compressed file. Attribute is read-only.

Function ScanFolder(FolderSpec As String, SearchStr As String) As String
    Dim thisFolder As Folder
    Dim allFolders As Folders
    Dim thisFile As File
    Dim allFiles As Files
    Set thisFolder = FSys.GetFolder(FolderSpec)
    Set allFolders = thisFolder.SubFolders
    For Each thisFolder In allFolders
        If (thisFolder.Attributes And Hidden) <> Hidden Then   ' Leave hidden directories alone
            Set allFiles = thisFolder.Files
            If allFiles.Count > 0 Then
                For Each thisFile In allFiles
                    If Right(thisFile.Name, 4) = SearchStr Then
                        List1.AddItem thisFolder.Path & "\" & thisFile.Name
                    End If
                Next
            End If
            Set allFiles = Nothing
            Call ScanFolder(thisFolder.Path, SearchStr)
        End If
        DoEvents
    Next
    Set thisFolder = Nothing
    Set allFolders = Nothing
    Exit Function
End Function
 
Private Sub Command1_Click()
    Dim StartTime As String
    List1.Clear
    StartTime = Now
    MousePointer = vbHourglass
    Call ScanFolder("C:\", ".vbp")
    MousePointer = vbHourglass
    MsgBox "ScanFolders Complete - " & DateDiff("s", StartTime, Now) & " Seconds"
End Sub
 
Private Sub Form_Load()
    Set FSys = New FileSystemObject
End Sub
 
'Method 2

'Using API

Option Explicit
 
Const MAX_PATH = 260
Const MAXDWORD = &HFFFF
Const INVALID_HANDLE_VALUE = -1
Const FILE_ATTRIBUTE_ARCHIVE = &H20
Const FILE_ATTRIBUTE_DIRECTORY = &H10
Const FILE_ATTRIBUTE_HIDDEN = &H2
Const FILE_ATTRIBUTE_NORMAL = &H80
Const FILE_ATTRIBUTE_READONLY = &H1
Const FILE_ATTRIBUTE_SYSTEM = &H4
Const FILE_ATTRIBUTE_TEMPORARY = &H100
 
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
 
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
 
Private Function ScanFolder(Path As String, SearchStr As String) As String
    Dim FileName As String
    Dim DirName As String
    Dim dirNames() As String
    Dim nDir As Integer
    Dim i As Integer
    Dim hSearch As Long
    Dim WFD As WIN32_FIND_DATA
    Dim Cont As Integer
    Dim FileSize As Long
    Dim FoundName As String
 
    DoEvents
    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
                    nDir = nDir + 1
                    ReDim Preserve dirNames(nDir)
                End If
            End If
            Cont = FindNextFile(hSearch, WFD)    'Get next subdirectory.
            DoEvents
        Loop
        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)
            List1.AddItem Path & FileName
            Cont = FindNextFile(hSearch, WFD)    ' Get next file
            DoEvents
        Wend
        Cont = FindClose(hSearch)
    End If
    If hSearch = -1 Then
        ' If there are sub-directories...
        If nDir > 0 Then
            ' Recursively walk into them...
            For i = 0 To nDir - 1
                FoundName = ScanFolder(Path & dirNames(i) & "\", SearchStr)
                If FoundName <> "" Then
                    ScanFolder = FoundName
                    Exit Function
                End If
                DoEvents
            Next i
        End If
    End If
    DoEvents
End Function
 
Private 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
 
Private Sub Command1_Click()
    Dim StartTime As String
    List1.Clear
    StartTime = Now
    MousePointer = vbHourglass
    Call ScanFolder("C:\", "*.vbp")
    MousePointer = vbNormal
    MsgBox "ScanFolders Complete - " & DateDiff("s", StartTime, Now) & " Seconds"
End Sub
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment


 

No trackbacks yet.