DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 11.11 Set File Date and Time Stamps

11.11.1 Problem

Access makes it easy to retrieve the modification date and time for files on disk, using the FileDateTime function. In one application, though, you need to be able to reset the last-modification date of files manually; the Access FileCopy function doesn't reset file date and time stamps, and you'd like copied files to have the current time. Is there a Windows API call that allows you to set file date and time stamps?

11.11.2 Solution

Windows provides the GetFileTime and SetFileTime API functions. Both work with three different date/time values: date of creation, date of last access, and date of last write. You want to preserve the date of creation and update the dates of last access and update. The code shown in this example will allow you to do this.

The sample form, frmTimeStamp, allows you to select a filename. The function then displays the date and time of last modification for the file, as shown in Figure 11-13. In addition, you can set a new file date, time, or both (the function retains whichever setting you don't change, if you just change one).

Figure 11-13. frmTimeStamp shows a selected file's modification date and time
figs/acb2_1113.gif

To set file date and time information in your own applications, follow these steps:

  1. Import the module basTimeStamp from 11-11.MDB. This module includes the type definitions and Windows API declarations you'll need, as well as a VBA function to convert dates and times as retrieved from the API call into date/time values that Access can understand. If you want to use this sample form in your own applications, you'll also need to import basFillList, which includes functions to retrieve the list of files.

  2. To set the modification-date information for a specific file, call the acbSetFileDateTime function, passing it a filename and a date/time value as parameters. For example, the following code will change the last-modification time and date for C:\AUTOEXEC.BAT to the current date and time:

    blnOK = acbSetFileDateTime("C:\AUTOEXEC.BAT", Now)

11.11.3 Discussion

The acbSetFileDateTime function consists of three basic steps. Its source code is:

Public Function acbSetFileDateTime( _
 strFileName As String, varDate As Date) As Boolean
   Dim hFile As Long
   Dim of As OFSTRUCT
   Dim st As SYSTEMTIME
   Dim ftCreation As FILETIME
   Dim ftLastAccess As FILETIME
   Dim ftLastWrite As FILETIME
   Dim ftLocal As FILETIME
   Dim blnOK As Boolean
   
   st.wYear = Year(varDate)
   st.wMonth = Month(varDate)
   st.wDay = Day(varDate)
   st.wHour = Hour(varDate)
   st.wMinute = Minute(varDate)
   st.wSecond = Second(varDate)
   
   hFile = OpenFile(strFileName, of, OF_READWRITE)
   If hFile > 0 Then
      blnOK = GetFileTime(hFile, ftCreation, ftLastAccess, ftLastWrite)
      If blnOK Then blnOK = SystemTimeToFileTime(st, ftLastWrite)
      If blnOK Then blnOK = LocalFileTimeToFileTime(ftLastWrite, ftLocal)
      If blnOK Then blnOK = SetFileTime(hFile, ftCreation, ftLocal, ftLocal)
      CloseHandle hFile
   End If
   acbSetFileDateTime = blnOK
End Function

The first step the function takes is to copy the date information from the Access Date-type variable into a structure that the API can use:

' In the declarations section:
Private Type SYSTEMTIME
   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

' In the function:
Dim st As SYSTEMTIME

st.wYear = Year(varDate)
st.wMonth = Month(varDate)
st.wDay = Day(varDate)
st.wHour = Hour(varDate)
st.wMinute = Minute(varDate)
st.wSecond = Second(varDate)

Next, the function must open the requested file with read/write access so that it can write to the file's time stamp:

hFile = OpenFile(strFileName, of, OF_READWRITE)

If this succeeds, the function then retrieves the current time stamps, converts the system time structure to a file time structure, converts that time from local time to the internal generalized time that Windows uses, and finally sets the file time:

blnOK = GetFileTime(hFile, ftCreation, ftLastAccess, ftLastWrite)
If blnOK Then blnOK = SystemTimeToFileTime(st, ftLastWrite)
If blnOK Then blnOK = LocalFileTimeToFileTime(ftLastWrite, ftLocal)
If blnOK Then blnOK = SetFileTime(hFile, ftCreation, ftLocal, ftLocal)
CloseFileHandle hFile

The function sets both the time of last access and the time of last write to be the date and time you've specified.

When you select the Set button on the sample form, Access executes the following procedure:

Private Sub cmdSetTime_Click( )
   Dim varDate As Date
   Dim strDate As String
   Dim strTime As String
   
   strDate = IIf(IsNull(Me.txtNewDate), Me.txtDate, Me.txtNewDate)
   strTime = IIf(IsNull(Me.txtNewTime), Me.txtTime, Me.txtNewTime)
   varDate = CVDate(strDate & " " & strTime)
   If Not acbSetFileDateTime(GetPath( ), varDate) Then
      MsgBox "Unable to set the file date!"
   Else
      Me.txtDate = Format(varDate, "Short Date")
      Me.txtTime = Format(varDate, "Short Time")
   End If
End Sub

This procedure retrieves the dates you've typed on the form, converts them to an Access date/time value, and then sets the date for the file you've selected. Note that the example uses the existing date or time for any value you didn't enter. Because the Set button isn't enabled unless you enter at least the date or the time, there's no need to worry about when they're both null.

Unless you take the extra step of converting the passed-in date/time value from local time to the internal time Windows uses (Greenwich Mean Time), the time you set will be off by the difference in time zones between your time and the standardized time. The call to LocalTimeToFileTime takes care of this for you. Of course, this counts on the local time having been set correctly on the local system.

    [ Team LiB ] Previous Section Next Section