Welcome to ™️ Mak-Nur | Forum ™️

Silakan Daftar untuk bergabung

Dan silakan Login untuk memasuki forum

Tinggalkan Komentar anda Bila Selesai MendownLoad Smile

kami akan mengganti nama domain.
selalu baca Pemberitahuan/Announcement dari kami.

maknur Comunity Site

Mak-Nur Comunity Site
HomeHome  RegisterRegister  Log inLog in  FacebookFacebook  

Share | 

 How to use FindFirstFile Win32 API from Visual Basic code

Go down 
Administrator Maknur™
Administrator Maknur™

Jumlah posting : 54
Join date : 2010-09-21

PostSubject: How to use FindFirstFile Win32 API from Visual Basic code   Fri Dec 24, 2010 9:53 am

Download Visual Basic code for this article here:
Who should read this article?

This article is intended for advanced Visual Basic programmers. It
may be interesting for programmers studying Visual Basic programming
language as well.

You will need a basic knowledge of the Visual Basic programming
language and Win32 API. You need Microsoft Visual Basic 6.0 development
environment installed at your computer.
What the difference between FindFirstFile Win32 API function and Dir Visual Basic function?

Both functions search a directory for a file whose name matches the
specified pattern, but input parameters, results and using are quite
The Dir Visual Basic function input parameters:

  • pathname optional parameter with the file name pattern
  • attributes optional parameter with the file attribute pattern

The Dir function returns a String value representing the name of file or directory that matches file name and/or file attribute patterns.
If you decide to list all files in the some directory and specify the file name pattern, then you need to call the Dir function without parameters until it will return empty string.
The FindFirstFile Win32 API function input parameters:

  • lpFileName - the same as pathname parameter of the Dir function
  • lpFindFileData - pointer to the buffer that receives information about the found file or subdirectory. WIN32_FIND_DATA structure should be used as buffer.

The FindFirstFile function returns a Long value representing a search handle, if the function succeeds, or INVALID_HANDLE_VALUE, if the function fails.
You need to call the FindNextFile Win32 API function with
returned search handle subsequently, if you want to list all files in
the directory. You must close the search handle by using the FindClose function when it is no longer needed.
One more distinctive feature: according to my tests, FindFirstFile/FindNextFile Win32 API functions work twice as faster then the Dir Visual Basic function.
The FindFirstFile Win32 API function output

Lets review output of the FindNextFile Win32 API function more closely. It populates the WIN32_FIND_DATA structure if some file was found.
Here is the definition of this structure:
typedef struct _WIN32_FIND_DATA
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cAlternateFileName[14];

We obtain the following extended file info:

  • dwFileAttributes - file attributes
  • ftCreationTime - structure that specifies when the file was created
  • ftLastAccessTime - structure that specifies when the file was last read from or written to
  • ftLastWriteTime - structure that specifies when the file was last written to
  • nFileSizeHigh, nFileSizeLow - file size, in bytes
  • cFileName - null-terminated string that is the name of the file
  • cAlternateFileName - null-terminated string that is an alternative name for the file in the classic 8.3 format

As you can see, we can get all this information by one function call only. We don't need to call GetAttr, FileLen or FileDateTime Visual Basic functions separately. It's a quite big saving of time.
Using of the FindFirstFile Win32 API from Visual Basic code

We need the following declarations in our Visual Basic code:
The FindFirstFile Win32 API function, which creates a search handle and obtains first file info
Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" _
(ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long

The FindNextFile Win32 API function, which continues a file search from a previous call to the FindFirstFile function
Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" _
(ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long

The FindClose Win32 API function, which closes the search handle created by the FindFirstFile function
Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long

The WIN32_FIND_DATA structure that we need to receive the FindFirstFile and the FindNextFile functions output
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
cAlternateFileName As String * 14
End Type

The INVALID_HANDLE_VALUE is return value, which indicates that the FindFirstFile function failed

File name is limited to MAX_PATH characters
Const MAX_PATH As Integer = 260

The FILETIME structure is a 64-bit value representing UTC-based date and time of file
dwLowDateTime As Long
dwHighDateTime As Long
End Type

You may notice two disadvantages of the WIN32_FIND_DATA structure from the point of view of Visual Basic programming:

  • cFileName and cAlternateFileName fields are fixed-length null-terminated strings. So we need TrimNull function, which will extract actual file name from such strings.
  • All file dates are packed in the FILETIME structures. Therefore, we need some additional FileTimeToDate function to convert them to the VB Date format.

Here is source code for the TrimNull function:
Function TrimNull(sFileName As String) As String
Dim i As Long
' Search for the first null character
i = InStr(1, sFileName, vbNullChar)
If i = 0 Then
TrimNull = sFileName
' Return the file name
TrimNull = Left$(sFileName, i - 1)
End If
End Function

I think this function is quite simple and doesn't require additional comments.
Now lets implement the FileTimeToDate conversion function. We need two additional Win32 API functions to accomplish this task.
The FILETIME structure contains UTC-based file date and time.
Therefore, we need to convert it to the local time according to the
current settings for the time zone and daylight saving time.
The FileTimeToLocalFileTime function converts a file time to a local file time
Declare Function FileTimeToLocalFileTime Lib "kernel32" _
(lpFileTime As FILETIME, lpLocalFileTime As FILETIME) As Long

The FileTimeToSystemTime function converts a file time to system time format. It populates the SYSTEMTIME structure, which can be easily used to create Visual Basic Date value.
Declare Function FileTimeToSystemTime Lib "kernel32" _
(lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As Long

Here is the SYSTEMTIME structure, which represents date and time
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type

The FileTimeToDate function gets UTC-based file date and time packed in the FILETIME structure and converts it to the Visual Basic Date value.
Function FileTimeToDate(lpFileTime As FILETIME) As Date
Dim lpLocalFileTime As FILETIME
Dim lpSystemTime As SYSTEMTIME
Dim dResult As Date
dResult = Empty
' Convert from UTC-based to the local file time
If FileTimeToLocalFileTime(lpFileTime, lpLocalFileTime) Then
' Unpack FILETIME structure to SYSTEMTIME structure
If FileTimeToSystemTime(lpLocalFileTime, lpSystemTime) Then
' Create Visual Basic Date value
dResult = DateSerial(lpSystemTime.wYear, _
lpSystemTime.wMonth, lpSystemTime.wDay) _
+ TimeSerial(lpSystemTime.wHour, _
lpSystemTime.wMinute, lpSystemTime.wSecond)
End If
End If
FileTimeToDate = dResult
End Function

We have used DateSerial and TimeSerial standard Visual Basic functions to create resulting Date value.
Finally lets review code sample. This code populates txtResult textbox with the list of all files from the location specified in the txtPath textbox. Please note that correct pattern should be specified in the txtPath textbox, i.e. "C:*.*", but not "C:".
' Buffer for output result
Dim sBuff As String
' File search handle
Dim iSearchHandle As Long
' File search buffer
Dim pFindFileBuff As WIN32_FIND_DATA
sBuff = vbNullString
' Find first file and create search handle
iSearchHandle = FindFirstFile(Me.txtPath.Text, pFindFileBuff)
' Check if FindFirstFile call was successful
If iSearchHandle <> INVALID_HANDLE_VALUE Then
' Store first file name and date in the buffer
sBuff = TrimNull(pFindFileBuff.cFileName) & " " _
& CStr(FileTimeToDate(pFindFileBuff.ftLastWriteTime)) & vbCrLf
' Find the rest of files with the FindNextFile function
Do While FindNextFile(iSearchHandle, pFindFileBuff)
sBuff = sBuff & TrimNull(pFindFileBuff.cFileName) & " " _
& CStr(FileTimeToDate(pFindFileBuff.ftLastWriteTime)) & vbCrLf
' Close file search handle
Call FindClose(iSearchHandle)
End If
' Show results
Me.txtResult.Text = sBuff

As you can see we have utilized all information reviewed above in
this small Visual Basic sample. Feel free to download and run full
source code.
How to use sample Visual Basic code

Here are some recommendations on how to use sample Visual Basic code:

  • Unpack into a single folder on your computer.
  • Run compiled executable Project1.exe. It doesn't require any additional DLLs except Visual Basic run-time.
  • Or load Project1.vbp in your Visual Basic development environment to view sample sources.
Back to top Go down
How to use FindFirstFile Win32 API from Visual Basic code
Back to top 
Page 1 of 1

Permissions in this forum:You cannot reply to topics in this forum
MNC :: File Manipulation-
Jump to: