'接上面
Private Function SearchForFolders(FP As FILE_PARAMS) As Long
Dim WFD As WIN32_FIND_DATA
Dim hFile As Long
Dim sRoot As String
Dim sPath As String
Dim sTmp As String
Dim nCount As Long
sRoot = QualifyPath(FP.sFileRoot)
sPath = sRoot & FP.sFileNameExt
'obtain handle to the first match
hFile = FindFirstFile(sPath, WFD)
'if valid ...
If hFile <> INVALID_HANDLE_VALUE Then
Do
'We only want folders in this method.
If (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'remove trailing nulls
sTmp = TrimNull(WFD.cFileName)
'and if not the default system folders
If sTmp <> "." And sTmp <> ".." Then
'count it and add to the list if the flag indicates
nCount = nCount + 1
If FP.bList Then List1.AddItem sRoot & sTmp
'if a recursive search was selected, call
'this method again with a modified root
If FP.bRecurse Then
FP.sFileRoot = sRoot & sTmp
nCount = nCount + SearchForFolders(FP)
End If
'this is outside the recurse code in case
'a single path-search was specified
FP.nFileCount = nCount
End If
End If
Loop While FindNextFile(hFile, WFD)
'close the handle
hFile = FindClose(hFile)
End If
'since folders are 0-length, return the count instead
SearchForFolders = nCount
End Function
'接上面
Private Sub DisplayInit()
'common routine to initialize display
Text2.Text = "Working ..."
Text3.Text = ""
Text2.Refresh
Text3.Refresh
List1.Clear
List1.Clear
List1.Visible = False
End Sub
Private Sub DisplayResults(FP As FILE_PARAMS)
'a common routine to display search results
'this defaults to show the size and count
'containing in the FP type members, but if
'FP.sResult is filled (from the Drive and
'System search methods), that is shown instead.
Text2.Text = Format$(FP.nFileCount, sFmtResult) & _
" (" & FP.sFileNameExt & ")"
Text3.Text = Format$(FP.nFileSize, sFileSizeBytes)
If FP.sResult > "" Then
Text2.Text = "found: " & FP.bFound
Text3.Text = "location: " & FP.sResult
End If
List1.Visible = True
End Sub
Private Function QualifyPath(sPath As String) As String
'assures that a passed path ends in a slash
If Right$(sPath, 1) <> "\" Then
QualifyPath = sPath & "\"
Else: QualifyPath = sPath
End If
End Function
Function StripItem(startStrg As String) As String
'Take a string separated by Chr(0)'s,
and split off 1 item, and shorten the
'string so that the next item is ready
'for removal.
Dim pos As Integer
pos = InStr(startStrg, Chr$(0))
If pos Then
StripItem = Mid(startStrg, 1, pos - 1)
startStrg = Mid(startStrg, pos + 1, Len(startStrg))
End If
End Function
Public Function TrimNull(startstr As String) As String
'returns the string up to the first
'null, if present, or the passed string
Dim pos As Integer
pos = InStr(startstr, Chr$(0))
If pos Then
TrimNull = Left$(startstr, pos - 1)
Exit Function
End If
TrimNull = startstr
End Function
Private Function GetFileInformation(FP As FILE_PARAMS) As Long
'local working variables
Dim WFD As WIN32_FIND_DATA
Dim hFile As Long
Dim nSize As Long
Dim sPath As String
Dim sRoot As String
Dim sTmp As String
'FP.sFileRoot (assigned to sRoot) contains
'the path to search.
'
'FP.sFileNameExt (assigned to sPath) contains
'the full path and filespec.
sRoot = QualifyPath(FP.sFileRoot)
sPath = sRoot & FP.sFileNameExt
'obtain handle to the first filespec match
hFile = FindFirstFile(sPath, WFD)
'if valid ...
If hFile <> INVALID_HANDLE_VALUE Then
Do
'remove trailing nulls
sTmp = TrimNull(WFD.cFileName)
'Even though this routine uses filespecs,
'*.* is still valid and will cause the search
'to return folders as well as files, so a
'check against folders is still required.
If Not (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) _
= FILE_ATTRIBUTE_DIRECTORY Then
'file found, so increase the file count
FP.nFileCount = FP.nFileCount + 1
'retrieve the size and assign to nSize to
'be returned at the end of this function call
nSize = nSize + (WFD.nFileSizeHigh * (MAXDWORD + 1)) + WFD.nFile
SizeLow
'add to the list if the flag indicates
If FP.bList Then List1.AddItem sRoot & sTmp
End If
Loop While FindNextFile(hFile, WFD)
'close the handle
hFile = FindClose(hFile)
End If
End If
'return the size of files found
GetFileInformation = nSize
End Function
Private Function SearchPathForFile(FP As FILE_PARAMS) As Boolean
Dim sResult As String
'pad a return string and search the passed drive
sResult = Space(MAX_PATH)
'SearchTreeForFile returns True (1) if found,
'or False otherwise. If True, sResult holds
'the full path.
FP.bFound = SearchTreeForFile(FP.sFileRoot, FP.sFileNameExt, sResult)
'if found, strip the trailing nulls and exit
If FP.bFound Then
FP.sResult = LCase$(TrimNull(sResult))
End If
SearchPathForFile = FP.bFound
End Function
Private Function SearchSystemForFile(FP As FILE_PARAMS) As Boolean
Dim nSize As Long
Dim sBuffer As String
Dim currDrive As String
Dim sResult As String
'retrieve the available drives on the system
sBuffer = Space$(64)
nSize = GetLogicalDriveStrings(Len(sBuffer), sBuffer)
'nSize returns the size of the drive string
If nSize Then
'strip off trailing nulls
sBuffer = Left$(sBuffer, nSize)
'search each fixed disk drive for the file
Do Until sBuffer = ""
'strip off one drive item from sBuffer
FP.sFileRoot = StripItem(sBuffer)
'just search the local file system
If GetDriveType(FP.sFileRoot) = DRIVE_FIXED Then
'this may take a while, so update the
'display when the search path changes
Text2.Text = "Working ... searching drive " & FP.sFileRoot
Text2.Refresh
'pad a return string and search the passed drive
sResult = Space(MAX_PATH)
FP.bFound = SearchTreeForFile(FP.sFileRoot, FP.sFileNameExt, sRe
sult)
'if found, strip the trailing nulls and exit
If FP.bFound Then
FP.sResult = LCase$(TrimNull(sResult))
Exit Do
End If
End If
Loop
End If
SearchSystemForFile = FP.bFound
End Function
Private Function SearchForFiles(FP As FILE_PARAMS) As Double
'local working variables
Dim WFD As WIN32_FIND_DATA
Dim hFile As Long
Dim nSize As Long
Dim sPath As String
Dim sRoot As String
Dim sTmp As String
sRoot = QualifyPath(FP.sFileRoot)
sPath = sRoot & "*.*"
'obtain handle to the first match
hFile = FindFirstFile(sPath, WFD)
'if valid ...
If hFile <> INVALID_HANDLE_VALUE Then
'This is where the method obtains the file
'list and data for the folder passed.
'
'GetFileInformation function returns the size,
'in bytes, of the files found matching the
'filespec in the passed folder, so its
'assigned to nSize. It is not directly assigned
'to FP.nFileSize because nSize is incremented
'below if a recursive search was specified.
nSize = GetFileInformation(FP)
FP.nFileSize = nSize
Do
'if the returned item is a folder...
If (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'..and the Recurse flag was specified
If FP.bRecurse Then
'remove trailing nulls
sTmp = TrimNull(WFD.cFileName)
'and if the folder is not the default
'self and parent folders...
If sTmp <> "." And sTmp <> ".." Then
'..then the item is a real folder, which
'may contain other sub folders, so assign
'the new folder name to FP.sFileRoot and
'recursively call this function again with
'the ammended information.
'
'Since nSize is a local variable, whose value
'is both set above as well as returned as the
'function call value, the nSize needs to be
'added to previous calls in order to maintain accuracy.
'
'However, because the nFileSize member of
'FILE_PARAMS is passed back and forth through
'the calls, nSize is simply assigned to it
'after the recursive call finishes.
FP.sFileRoot = sRoot & sTmp
nSize = nSize + SearchForFiles(FP)
FP.nFileSize = nSize
End If
End If
End If
'continue looping until FindNextFile returns
'0 (no more matches)
Loop While FindNextFile(hFile, WFD)
'close the find handle
hFile = FindClose(hFile)
End If
'because this routine is recursive, return
'the size of matching files
SearchForFiles = nSize
End Function
采用递归的方法查找某一目录文件
BAS Module Code
Place the following into the general declarations area of a bas module:
----------------------------------------------------------------------------
----
Option Explicit
Public Const sFileSizeBytes = "###,###,###,###,###,###,##0 \b\y\t\e\s"
Public Const sFmtResult = "###,###,###,##0 \f\o\u\n\d"
Public Const sFileCount = "###,###,###,##0 f\i\l\e\s\ \f\o\u\n\d"
Public Const sFolderCount = "###,###,###,##0 f\o\l\d\e\r\s \f\o\u\n\d"
Public Const MAXDWORD = &HFFFFFFF
Public Const MAX_PATH = 260
Public Const INVALID_HANDLE_VALUE = -1
Public Const FILE_ATTRIBUTE_ARCHIVE = &H20
Public Const FILE_ATTRIBUTE_COMPRESSED = &H800
Public Const FILE_ATTRIBUTE_DIRECTORY = &H10
Public Const FILE_ATTRIBUTE_HIDDEN = &H2
Public Const FILE_ATTRIBUTE_NORMAL = &H80
Public Const FILE_ATTRIBUTE_READONLY = &H1
Public Const FILE_ATTRIBUTE_TEMPORARY = &H100
Public Const FILE_ATTRIBUTE_FLAGS = FILE_ATTRIBUTE_ARCHIVE Or _
FILE_ATTRIBUTE_HIDDEN Or _
FILE_ATTRIBUTE_NORMAL Or _
FILE_ATTRIBUTE_READONLY
Public Const DRIVE_UNKNOWNTYPE = 1
Public Const DRIVE_REMOVABLE = 2
Public Const DRIVE_FIXED = 3
Public Const DRIVE_REMOTE = 4
Public Const DRIVE_CDROM = 5
Public Const DRIVE_RAMDISK = 6
Public Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Public 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
'the custom-made UDT for searching
Public Type FILE_PARAMS
bRecurse As Boolean 'set True to perform a recursive search
bList As Boolean 'set True to add results to listbox
bFound As Boolean 'set only with SearchTreeForFile methods
sFileRoot As String 'search starting point, ie c:\, c:\winnt\
sFileNameExt As String 'filenae/filespec to locate, ie *.dll, notepad.ex
e
sResult As String 'path to file. Set only with SearchTreeForFile me
thods
nFileCount As Long 'total file count matching filespec. Set in FindX
XX only
nFileSize As Double 'total file size matching filespec. Set in FindXX
X only
End Type
Public Declare Function FindClose Lib "kernel32" _
(ByVal hFindFile As Long) As Long
Public Declare Function FindFirstFile Lib "kernel32" _
Alias "FindFirstFileA" _
(ByVal lpFileName As String, _
lpFindFileData As WIN32_FIND_DATA) As Long
Public Declare Function FindNextFile Lib "kernel32" _
Alias "FindNextFileA" _
(ByVal hFindFile As Long, _
lpFindFileData As WIN32_FIND_DATA) As Long
Public Declare Function SearchTreeForFile Lib "imagehlp.dll" _
(ByVal sFileRoot As String, _
ByVal InputPathName As String, _
ByVal OutputPathBuffer As String) As Boolean
Public Declare Function GetLogicalDriveStrings Lib "kernel32" Alias "GetLogi
calDriveStringsA" _
(ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Public Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" _
(ByVal nDrive As String) As Long
'--end block--'
Form Code
Create a new project with a form containing controls as shown in the illustr
ation, and configured as: three text boxes (Text1, Text2, Text3), a combo bo
x (Combo1), and four command buttons (Command1 - Command4). In addtion, add
two check boxes (chkRecurse and chkListResults). Finally, add a listbox (Lis
t1), lable as desired, and add the following code:
----------------------------------------------------------------------------
----
Option Explicit
Private Sub Form_Load()
With Combo1
.AddItem "*.*"
.AddItem "*.dll"
.AddItem "*.exe"
.AddItem "*.ini"
.AddItem "*.ocx"
.AddItem "*.vxd"
.ListIndex = 0
End With
End Sub
Private Sub Command1_Click()
Dim FP As FILE_PARAMS
Call DisplayInit
With FP
.sFileRoot = Text1.Text
.sFileNameExt = Combo1.Text
.bRecurse = chkRecurse.Value = 1
.bList = chkListResults.Value = 0
End With
Call SearchForFiles(FP)
Call DisplayResults(FP)
End Sub
Private Sub Command2_Click()
Dim FP As FILE_PARAMS
Call DisplayInit
With FP
.sFileRoot = Text1.Text
.sFileNameExt = "*.*"
.bRecurse = chkRecurse.Value = 1
.bList = chkListResults.Value = 0
End With
Call SearchForFolders(FP)
Call DisplayResults(FP)
End Sub
Private Sub Command3_Click()
Dim FP As FILE_PARAMS
Call DisplayInit
With FP
.sFileRoot = "c:\" '"c:\winnt\"
.sFileNameExt = "wordpad.exe" ' "notepad.exe"
End With
Call SearchPathForFile(FP)
Call DisplayResults(FP)
End Sub
Private Sub Command4_Click()
Dim FP As FILE_PARAMS
Call DisplayInit
With FP
.sFileRoot = "c:\"
.sFileNameExt = "vb6.exe" '"wordpad.exe"
End With
Call SearchSystemForFile(FP)
Call DisplayResults(FP)
End Sub
'接下面
您可以用Windows API或VB的文件操作函数,在指定路径下查找所需的文件。您可以参考这篇文章里面的代码例子:
HOWTO: Search Directories to Find or List Files (Q185476)
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q185476