Solved

Setting Last-Modified-Date

Posted on 2004-09-22
5
398 Views
Last Modified: 2012-06-21
Using API's I'd set the modified & created date & time of a file.But the problem is that the new date & time is not being properly set.My code is as follows:

Function SetFileTimes(sFilePath, mCreated, mLastModified)
    Dim rc As Long, hFile As Long
    Dim lpCreationTime As FILETIME
    Dim lpLastAccessTime As FILETIME
    Dim lpLastWriteTime As FILETIME
    Dim lpsCT As SYSTEMTIME
    Dim lpsLAT As SYSTEMTIME
    Dim lpsLWT As SYSTEMTIME
    Const GENERIC_READ = &H80000000
    Dim sa As SECURITY_ATTRIBUTES
   
   sa.nLength = Len(sa)
   sa.bInheritHandle = 1
   'Get a handle to the file
   hFile = CreateFile(ByVal sFilePath, GENERIC_READ, FILE_SHARE_READ, sa, _
                             4, FILE_ATTRIBUTE_NORMAL, 0)
   If hFile <> 0 Then
       'Convert creation date/time
       mCreated = #8/15/2004 11:19:00 PM#
       With lpsCT
            .wMonth = Month(mCreated)
            .wDay = Day(mCreated)
            .wYear = Year(mCreated)
            .wHour = Hour(mCreated)
            .wMinute = Minute(mCreated)
            .wSecond = Second(mCreated)
            .wMilliseconds = 1000 * Second(mCreated)
       End With
       rc = SystemTimeToFileTime(lpsCT, lpCreationTime)
       
       'Convert last-modified date/time
       mLastModified = #9/1/2004 9:30:30 PM#
       With lpsLWT
               .wMonth = Month(mLastModified)
               .wDay = Day(mLastModified)
               .wYear = Year(mLastModified)
               .wHour = Hour(mLastModified)
               .wMinute = Minute(mLastModified)
               .wSecond = Second(mLastModified)
               .wMilliseconds = 1000 * Second(mLastModified)
       End With
       rc = SystemTimeToFileTime(lpsLWT, lpLastWriteTime)

       'Save the new file dates & times
       rc = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime)

       'Close the file
       rc = CloseHandle(hFile) 'If the function succeeds, the return value is non-zero.
    End If
End Function
0
Comment
Question by:EXwithRaj
  • 2
  • 2
5 Comments
 
LVL 41

Expert Comment

by:graye
ID: 12125367
I see a few strange things...

1) Open the file with FILE_WRITE_ATTRIBUTES
2) Do a GetFileTime() first to populate the 3 fields (so you won't have a null lpLastAccessTime)
3) Milliseconds should be mLastModifed.milisecond
0
 
LVL 3

Accepted Solution

by:
Validor earned 50 total points
ID: 12125752
I've taken your code and modified it just enough to make it work.  There were only a few things that I changed.  I used VB6.

1) I obviously had to declare a bunch of things that you excluded.  Some of these will be silently ignored if not declared, such as GENERIC_READ and GENERIC_WRITE.  These will default to 0, which is incorrect.

2) I specified types for the function parameters.  

3) As a result of change #2, I wasn't sure which types you were passing, and to cut out any problems with date types on the parameters, I hard-coded date member values.

4) You did not specify GENERIC_WRITE in the FILECREATE call, which is required for SETFILETIME.

5) I change the result code variable names so that I can watch each one to see if any fail (they're not very descriptive, though.

6) I had to make sure I tacked on a +chr$(0) at the end fo the filename I passed.  Be sure that you're doing this, or add a check for it.

I suspect that the problems you're having are due to the #0 at the end of the filename, the missing GENERIC_WRITE, and possible failure of the FILE OPEN.  You should first set the hfile to -1 before the call, then after the call, check this for a -1 value (which equates to the constant INVALID_HANDLE_VALUE).  If it is -1, the CREATEFILE call failed.

Private Const GENERIC_ALL = &H10000000
Private Const GENERIC_EXECUTE = &H20000000
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000


Private Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100
Private Const FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000
Private Const FORMAT_MESSAGE_FROM_HMODULE = &H800
Private Const FORMAT_MESSAGE_FROM_STRING = &H400
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Private Const FORMAT_MESSAGE_IGNORE_INSERTS = &H200
Private Const FORMAT_MESSAGE_MAX_WIDTH_MASK = &HFF

Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long

Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle 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 Integer
End Type

Private Type FILETIME
        dwLowDateTime As Long
        dwHighDateTime As Long
End Type

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function SystemTimeToFileTime Lib "kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FILETIME) As Long
Private Declare Function SetFileTime Lib "kernel32" (ByVal hFile As Long, lpCreationTime As FILETIME, lpLastAccessTime As FILETIME, lpLastWriteTime As FILETIME) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long



Function SetFileTimes(sFilePath As String, mCreated As Date, mLastModified As Date)
    Dim rc As Long, rc2 As Long, rc3 As Long, rc4 As Long, rc5 As Long, hFile As Long
    Dim lpCreationTime As FILETIME
    Dim lpLastAccessTime As FILETIME
    Dim lpLastWriteTime As FILETIME
    Dim lpsCT As SYSTEMTIME
    Dim lpsLAT As SYSTEMTIME
    Dim lpsLWT As SYSTEMTIME
    Const GENERIC_READ = &H80000000
    Dim sa As SECURITY_ATTRIBUTES
   
   sa.nLength = Len(sa)
   sa.bInheritHandle = 1
   
   'Get a handle to the file
   hFile = CreateFile(ByVal sFilePath, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ, _
        sa, 4, FILE_ATTRIBUTE_NORMAL, 0)
       
                             
    MsgBox "Handle: " & hFile
   
   If hFile <> 0 Then
       'Convert creation date/time
       mCreated = #8/15/2004 11:19:00 PM#
       With lpsCT
       
'            .wMonth = Month(mCreated)
'            .wDay = Day(mCreated)
'            .wYear = Year(mCreated)
'            .wHour = Hour(mCreated)
'            .wMinute = Minute(mCreated)
'            .wSecond = Second(mCreated)
'            .wMilliseconds = 1000 * Second(mCreated)
       
            .wMonth = 1
            .wDay = 1
            .wYear = 2001
            .wHour = 0
            .wMinute = 0
            .wSecond = 0
            .wMilliseconds = 0
       End With
       rc4 = SystemTimeToFileTime(lpsCT, lpCreationTime)
       
        'Create last access time.
        With lpsLAT
       

       
            .wMonth = 4
            .wDay = 4
            .wYear = 2004
            .wHour = 0
            .wMinute = 0
            .wSecond = 0
            .wMilliseconds = 0
       End With
       rc5 = SystemTimeToFileTime(lpsLAT, lpLastAccessTime)

       
       'Convert last-modified date/time
       mLastModified = #9/1/2004 9:30:30 PM#
       With lpsLWT
               '.wMonth = Month(mLastModified)
               '.wDay = Day(mLastModified)
               '.wYear = Year(mLastModified)
               '.wHour = Hour(mLastModified)
               '.wMinute = Minute(mLastModified)
               '.wSecond = Second(mLastModified)
               '.wMilliseconds = 1000 * Second(mLastModified)
               
               .wMonth = 1
               .wDay = 2
               .wYear = 2001
               .wHour = 0
               .wMinute = 0
               .wSecond = 0
               .wMilliseconds = 0
       End With
       rc = SystemTimeToFileTime(lpsLWT, lpLastWriteTime)

       'Save the new file dates & times
       rc2 = SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime)
       If (rc2 = 0) Then
        MsgBox FormatErrorMsg(Err)
       
       End If
       
       'Close the file
       rc3 = CloseHandle(hFile) 'If the function succeeds, the return value is non-zero.
    End If
End Function

Function FormatErrorMsg(Err As Long) As String
    Dim S As String * 1000
    FormatMessage FORMAT_MESSAGE_FROM_SYSTEM, ByVal 0, Err, 0, S, Len(S), ByVal 0&
    FormatErrorMsg = Left$(S, InStr(S, vbNullChar) - 1)
End Function

Private Sub Command1_Click()
    SetFileTimes "c:\delme2.txt" + Chr$(0), "01-01-2001", "01-02-2004"
End Sub
0
 

Author Comment

by:EXwithRaj
ID: 12187732
You were right about opening the file in the Write mode.But there's no need for the NULL character at the end of the filepath.Sans it nothing wrong occurs(although MSDN states the use of the NULL).The CreateFile API can be replaced with the simpler OpenFile API.In addition,the SetFileTime API has these interesting,but inexplicable,traits:
a) Although the wMilliseconds member can be ignored but it's value must not exceed 999 - else SetFileTime will fail.
b) THe most BIZZARE trait is that the starting time of the day is not 12:00:00 AM
   but - hold your breath - 5:30:00 AM!This means you simply cannot assign the hour & minute,      using the Hour & Minute functions,to the wHour & wMinutes members of the SystemTime data-type.You've to convert the actual hours & minutes to a figure which when  added to 5:30:00 AM will result in the original time-figure.This makes the task that much more harder.
          Me think the person at Microsoft responsible for this had the habit of getting up at  5:30:00 AM which forced him to commit this perversity.Just because his/her day started at  5:30:00 AM does not mean the whole world gets up at 5:30:00 AM.
c) If the seconds is 10 fine but if it's any other value then SetFileTime  increases the value by 1.
d) If the time is between #12:00:00 AM#  & #5:29:00 AM# then the API advances the day by 1.
   This also is ridiculous!
      Apart from these,your code "MsgBox FormatErrorMsg(Err)" is a bit quizzy!Why are you using Err?Don't you think you must replace it with GetLastError?
0
 
LVL 3

Expert Comment

by:Validor
ID: 12193493
Regarding the FormatErrorMsg, this was mostly an oversight on my part.  I meant to take some of that out when I was done playing with it.  I was using it to troubleshoot only.

What I MEANT to be doing was calling msgbox Err.LastDLLError (is that right?) the same thing as GETLASTERROR in any other language.  In VB, they say not to use GetLastError because the VB runtimes will make calls that overwrite it at times.  

In addition, I shouldn't have named the parameter ERR anyway, because it introduces ambiguity in the local scope.  If I were you, I would omit all the ERR, FormatErrorMsg stuff and forget you ever saw it :)
0
 

Author Comment

by:EXwithRaj
ID: 12256539
Validor,what about my observations on the SetFileTime API?Why've you made no comments on that?Have you verified the same in your computer?Have you had the same experience?I need to know so that I can validate my own observations on my computer.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
changeXy challenge 13 57
groovy example issue 10 66
White board coding practice 3 61
How can i compile this github project?? 2 41
Purpose To explain how to place a textual stamp on a PDF document.  This is commonly referred to as an annotation, or possibly a watermark, but a watermark is generally different in that it is somewhat translucent.  Watermark’s may be text or graph…
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now