Visual Basic File API Routines
SetFileTime: Modify the Date/Time of Folders and Files
     
Posted:   Saturday September 21, 2002
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows XP
OS restrictions:   Windows NT/2000/XP
Author:   VBnet - Randy Birch
     

Related:  

SetFileTime: Obtain and Change a File's Created, Accessed and Modified Dates
     
 Prerequisites
Windows NT4, Windows 2000 or Windows XP.

Changing the created, accessed or modified date of files or folders under Windows NT, 2000 or XP requires only a few simple API calls. By using CreateFile's special FILE_FLAG_BACKUP_SEMANTICS flag we can obtain a handle to a folder or file and, with SetFileTime, change its created, accessed or modified dates. When dealing with folders, the created date is reflected in the folder's property window, while Explorer shows the modified date (which under normal circumstances is always the same as the created date). Under Windows XP at least, the last accessed date of a folder is never shown.

To change the folder or file time, the SYSTEMTIME structure is populated with the day, month and year, and hour, minute and second of the desired date / time. However, when those values are used directly in a call to SetFileTime, Windows interprets the values passed as reflecting a Universal Coordinated Time (UTC) - aka a time at Greenwich mean time (GMT). In order for the date / time entered to be properly reflected with the SetFileTime call, the values contained in the SYSTEMTIME structure must first be converted to a FILETIME structure via SystemTimeToFileTime, and then the system must apply the local system's time-zone bias via LocalFileTimeToFileTime. Once the FILETIME structure has been changed, it is passed to SetFileTime and the new folder or file date / time is set.

Note that the code used in this method differs considerably from that used to change a file's created, accessed or modified date / time under Windows 9x (a method which is also applicable to NT-based machines), in that this method requires obtaining the folder's handle via CreateFile with the NT-specific FILE_FLAG_BACKUP_SEMANTICS flag set. The 9x-compatible method uses OpenFile to obtain the file handle where the FILE_FLAG_BACKUP_SEMANTICS flag is not supported.

Command1 ("New Date") is provided as a convenience to rapidly test this code and just calls a routine to randomly select values from the combo. Command2 ("Change Date") executes the APIs responsible for the date change.

 BAS Module Code
None.

 Form Code
The form consists of three text boxes (Text1 - Text3), two command buttons (Command1, Command2) and six combo boxes (Combo1 - Combo6). Label as desired and add the following code:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_DELETE As Long = &H4
Private Const FILE_FLAG_BACKUP_SEMANTICS = &H2000000
Private Const OPEN_EXISTING = 3

Private Type FILETIME
  dwLowDateTime     As Long
  dwHighDateTime    As Long
End Type

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 Long
End Type

Private Declare Function CreateFile Lib "kernel32" _
   Alias "CreateFileA" _
  (ByVal lpFileName As String, _
   ByVal dwDesiredAccess As Long, _
   ByVal dwShareMode As Long, _
   ByVal lpSecurityAttributes As Long, _
   ByVal dwCreationDisposition As Long, _
   ByVal dwFlagsAndAttributes As Long, _
   ByVal hTemplateFile As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" _
  (ByVal hObject As Long) As Long

Private Declare Function GetFileTime Lib "kernel32" _
  (ByVal hFile As Long, _
   lpCreationTime As FILETIME, _
   lpLastAccessTime As FILETIME, _
   lpLastWriteTime As FILETIME) As Long
   
Private Declare Function FileTimeToLocalFileTime Lib "kernel32" _
  (lpFileTime As FILETIME, _
   lpLocalFileTime As FILETIME) As Long

Private Declare Function FileTimeToSystemTime Lib "kernel32" _
  (lpFileTime As FILETIME, _
   lpSystemTime As SYSTEMTIME) As Long

Private Declare Function SystemTimeToFileTime Lib "kernel32" _
  (lpSystemTime As SYSTEMTIME, _
   lpFileTime As FILETIME) As Long

Private Declare Function LocalFileTimeToFileTime Lib "kernel32" _
  (lpLocalFileTime As FILETIME, _
   lpFileTime As FILETIME) As Long

Private Declare Function SetFileTime Lib "kernel32" _
  (ByVal hFile As Long, _
   lpCreationTime As FILETIME, _
   lpLastAccessTime As Any, _
   lpLastWriteTime As Any) As Long



Private Sub Form_Load()

   Dim cnt As Long
   
  'days
   With Combo1
      For cnt = 1 To 31
         .AddItem cnt
      Next
   End With
   
  'months
   With Combo2
      For cnt = 1 To 12
         .AddItem MonthName(cnt)
         .ItemData(.NewIndex) = cnt
      Next
   End With
   
  'years (note: if you change this
  'range, also change the Combo3
  'random number maximum in
  'SelectNewTestDate)
   With Combo3
      For cnt = 1980 To 2002
         .AddItem cnt
      Next
   End With
   
  'hours
   With Combo4
      For cnt = 1 To 24
         .AddItem cnt
      Next
   End With
      
  'minutes
   With Combo5
      For cnt = 0 To 59
         .AddItem cnt
      Next
   End With
   
  'seconds
   With Combo6
      For cnt = 0 To 59
         .AddItem cnt
      Next
   End With
      
   Randomize Timer
   Call SelectNewTestDate
   Command1.Caption = "New Date"
   Command1.TabIndex = 0
   Command2.Caption = "Change Date"
   
End Sub


Private Sub Command1_Click()

  'select a new set of list indicies
   Call SelectNewTestDate
   
End Sub


Private Sub Command2_Click()

   Dim hFolder As Long
   
  'obtain handle to the folder specified
  'in Text1
   hFolder = GetFolderFileHandle(Text1.Text)
   
   If (hFolder <> 0) And (hFolder > -1) Then
   
     'show the current folder date/time info
      Call GetFolderFileDate(hFolder, Text2)
   
     'attempt to change the date/time to the
     'values set in the combos
      If ChangeFolderFileDate(hFolder) Then
      
        'show the new folder date/time info
         Call GetFolderFileDate(hFolder, Text3)
      
      Else
      
         Text3.Text = "ChangeFolderFileDate failed."
      
      End If
   
     'clean up. If hfolder = -1 on a subsequent
     'run, you didn't close the hFolder handle.
     'Save the project and exit VB to release
     'the handle, then restart VB and re-run.
      Call CloseHandle(hFolder)
   
   Else
      
      Text2.Text = "Specified folder/file not found"
   
   End If
   

End Sub


Private Function ChangeFolderFileDate(ByVal hFolder As Long) As Boolean

   Dim st As SYSTEMTIME
   Dim ft As FILETIME
   
  'set the day, month and year, and
  'the hour, minute and second to the
  'values representing the desired date/time
   With st
      .wDay = Combo1.List(Combo1.ListIndex)
      .wMonth = Combo2.ItemData(Combo2.ListIndex)
      .wYear = Combo3.List(Combo3.ListIndex)

      .wHour = Combo4.List(Combo4.ListIndex)
      .wMinute = Combo5.List(Combo5.ListIndex)
      .wSecond = Combo6.List(Combo6.ListIndex)
   End With
      
   
  'call SystemTimeToFileTime to convert the system
  'time (st) to a file time (ft)
   If SystemTimeToFileTime(st, ft) = 1 Then
   
     'call LocalFileTimeToFileTime to convert the
     'local file time to a file time based on the
     'Coordinated Universal Time (UTC). Conveniently, 
     'the same FILETIME can be used as the in/out 
     'parameters!
      If LocalFileTimeToFileTime(ft, ft) = 1 Then
      
        'and call SetFileTime to set the date and
        'time that a file was created, last accessed,
        'and/or last modified (in this case all to
        'the same date/time). Since SetFileTime
        'returns 1 if successful, cast to return
        'a Boolean indicating failure or success.
         ChangeFolderFileDate = SetFileTime(hFolder, ft, ft, ft) = 1
         
      End If
   End If

End Function


Private Sub GetFolderFileDate(ByVal hFolder As Long, txt As TextBox)

   Dim FT_CREATE As FILETIME
   Dim FT_ACCESS As FILETIME
   Dim FT_WRITE As FILETIME
   Dim buff As String
   
  'fill in the FILETIME structures for the
  'created, accessed and modified date/time info
   If GetFileTime(hFolder, FT_CREATE, FT_ACCESS, FT_WRITE) = 1 Then
      
      buff = "Created:" & vbTab & GetFolderFileDateString(FT_CREATE) & vbCrLf
      buff = buff & "Access'd:" & vbTab & GetFolderFileDateString(FT_ACCESS) & vbCrLf
      buff = buff & "Modified:" & vbTab & GetFolderFileDateString(FT_WRITE)
      
      txt.Text = buff
   
   End If
   
End Sub


Private Function GetFolderFileDateString(ft As FILETIME) As String

   Dim ds As Single
   Dim ts As Single
   Dim ft_local As FILETIME
   Dim st As SYSTEMTIME
   
  'convert the file time to a local
  'file time
   If FileTimeToLocalFileTime(ft, ft_local) Then
    
     'convert the local file time to
     'the system time format
      If FileTimeToSystemTime(ft_local, st) Then
      
        'calculate the DateSerial/TimeSerial 
        'values for the system time
         ds = DateSerial(st.wYear, st.wMonth, st.wDay)
         ts = TimeSerial(st.wHour, st.wMinute, st.wSecond)
         
        'and return a formatted string
         GetFolderFileDateString = FormatDateTime(ds, vbLongDate) & "  " & _
                                   FormatDateTime(ts, vbLongTime)
                             
      End If
    End If
    
End Function


Private Function GetFolderFileHandle(sPath As String) As Long

  'open and return a handle to the folder
  'for modification.
  '
  'The FILE_FLAG_BACKUP_SEMANTICS flag is only
  'valid on Windows NT/2000/XP, and is usually
  'used to indicate that the file (or folder) is
  'being opened or created for a backup or restore
  'operation. The system ensures that the calling
  'process overrides file security checks, provided
  'it has the necessary privileges (SE_BACKUP_NAME
  'and SE_RESTORE_NAME).
  '
  'In our case, specifying this flag obtains a handle to
  'a directory, and a directory handle can be passed to
  'some functions (e.g.. SetFileTime) in place of a file handle.
   GetFolderFileHandle = CreateFile(sPath, _
                                    GENERIC_READ Or GENERIC_WRITE, _
                                    FILE_SHARE_READ Or FILE_SHARE_DELETE, _
                                    0&, _
                                    OPEN_EXISTING, _
                                    FILE_FLAG_BACKUP_SEMANTICS, _
                                    0&)
                                
End Function


Private Sub SelectNewTestDate()

  'this just selects a new random
  'number for each combo, thereby
  'providing an easy test bed for
  'changing test dates
   Combo1.ListIndex = Int(Rnd * 31) 'days
   Combo2.ListIndex = Int(Rnd * 12) 'months
   Combo3.ListIndex = Int(Rnd * 23) 'years
  
   Combo4.ListIndex = Int(Rnd * 24) 'hours
   Combo5.ListIndex = Int(Rnd * 60) 'minutes
   Combo6.ListIndex = Int(Rnd * 60) 'seconds
   
End Sub
 Comments
Run your project, and enter a valid folder or filename. This project does not prompt before changing, nor does it provide an undo, so take care applying it to valuable folders while testing.

Pressing the New Date button cycles through random date/times.  The Change button will update the folder or file specified, with the old file dates reflected in Text2, and the new dates after SetFileTime shown in Text3.


 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter