I recently needed a means of finding and reading an INI file on users' hard drives to determine where to export data to an external program. Although most users had the file stored in a standard folder location, some had installed it elsewhere, and a few had more than one copy!
I modified some VB code I had used in another project to create the Listfiles() utility which served my needs.
The utility uses two Win32 API calls to locate a file on the user's hard drive, even if you don't know it's path. It even locates multiple copies of a file and returns their paths as an array along with a count.
If the count is zero, the file doesn't exist. If it's more than 1, I used the array in a listbox and prompted the user to select the file to use.
The code below could be pasted into an agent to illustrate how the Listfiles() utility works.
Of course, this code will only work in Win32 environments (Win98, Win2000, Win NT 4.0).
Const FILE_ATTRIBUTE_DIRECTORY = &H10 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 * 260 cAlternate As String * 14 End Type Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" ( Byval lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" ( Byval hndFileFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long Declare Function FindClose Lib "kernel32" (Byval hndFileFile As Long) As Long Sub Initialize Dim FileList() As String Dim RootPath As String Dim FileMatch As String Dim FileCount As Integer RootPath = "C:" FileMatch = "TESTFILE.TXT" Call ListFiles(RootPath, FileMatch, FileList, FileCount) Forall p In FileList Print p End Forall Print FileCount End Sub Private Sub ListFiles(RootPath As String, FileMatch As String, FileList() As String, FileCount As Integer) Dim hndFile As Long Dim FileData As WIN32_FIND_DATA Dim fPath As String Dim fName As String Dim fPathName As String Dim fTmp As String Dim NameLn, MatchLn, FileFound As Integer fPath = RootPath If Right$(fPath, 1) <> "" Then fPath = fPath & "" End If MatchLn = Len(FileMatch) FileMatch = Lcase$(FileMatch) hndFile = FindFirstFile(fPath & "*", FileData) FileFound = (hndFile > 0) Do While FileFound fTmp = FileData.cFileName fName = Left$(fTmp, (Instr(fTmp, Chr$(0)) - 1)) NameLn = Len(fName) fPathName = fPath & fName If fName = "." Or fName = ".." Then ' Nothing Elseif FileData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY Then Call ListFiles( fPathName, FileMatch, FileList, FileCount) Elseif MatchLn > NameLn Then ' Nothing Elseif Lcase$(Right$(fName, MatchLn)) = FileMatch Then Redim Preserve FileList(FileCount ) FileList(FileCount) = fPathName FileCount = FileCount + 1 End If FileFound = FindNextFile(hndFile, FileData) Loop ' Close file FindClose hndFile End Sub
This was first published in October 2001