Announcement

Collapse
No announcement yet.

How to get the date and time of creation of a file

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to get the date and time of creation of a file

    Hi All
    How to get the date and time of creation of a file ? Let's say I would like to know the date and time of creation of the file
    located in the hard disk with the name of
    C:\Program Files (x86)\Microsoft Office\Office12\ACCDDS.DLL

    How do I write a program to retrieve the date and time of its creation and modification ?
    Thank you in advance


  • #2
    To get a file time, you call GetFileTime...

    Code:
    '16,896 bytes
    #COMPILE EXE '#Win#
    #DIM ALL
    #INCLUDE "Win32Api.inc"
    '______________________________________________________________________________
    
    FUNCTION FileNameGet(hOwner AS DWORD, sInitialFolder AS STRING, sFilter AS STRING, FilterIndex As LONG) AS STRING
     LOCAL OpenFileNameStruct AS OPENFILENAME
     LOCAL zFileName          AS ASCIIZ * %MAX_PATH
     LOCAL sCaption           AS STRING
     LOCAL sFilename          AS STRING
    
     IF LEN(sInitialFolder)             = 0 THEN sInitialFolder = CURDIR$
     IF LEN(sFilter)                    = 0 THEN sFilter = "All Files (*.*)" & $NUL & "*.*" & $NUL & $NUL
     OpenFileNameStruct.lStructSize     = SIZEOF(OPENFILENAME)
     OpenFileNameStruct.hWndOwner       = hOwner
     OpenFileNameStruct.lpstrFilter     = STRPTR(sFilter)
     OpenFileNameStruct.nFilterIndex    = 1 'For demo purpose
     sCaption                           = "Choose Filename"
     OpenFileNameStruct.lpstrTitle      = STRPTR(sCaption)
     OpenFileNameStruct.lpstrInitialDir = STRPTR(sInitialFolder)
     OpenFileNameStruct.lpstrFileTitle  = VARPTR(zFileName)
     OpenFileNameStruct.nMaxFileTitle   = SIZEOF(zFileName)
     sFilename                          = NUL$(%MAX_PATH)
     OpenFileNameStruct.lpstrFile       = STRPTR(sFilename)
     OpenFileNameStruct.nMaxFile        = LEN(sFilename)
     OpenFileNameStruct.Flags           = %OFN_CREATEPROMPT OR %OFN_FILEMUSTEXIST
    
     GetOpenFileName(OpenFileNameStruct)
     FilterIndex = OpenFileNameStruct.nFilterIndex
     sFilename   = RTRIM$(sFilename, $NUL)
     IF LEN(sFilename) THEN FUNCTION = sFilename 'With path
    
    END FUNCTION
    '_____________________________________________________________________________
    
    FUNCTION GetDateTimeFormat(FileDate AS FILETIME) AS STRING
     LOCAL LocalDate  AS FILETIME
     LOCAL SystemDate AS SYSTEMTIME
    
     FileTimeToLocalFileTime(FileDate, LocalDate) 'Convert from UTC to local time
     FileTimeToSystemTime(LocalDate, SystemDate)  'Convert to human readeable format
    
     FUNCTION = _ 'Format the resulting date, time and weekday
       FORMAT$(SystemDate.wyear, "0000") & "/" & FORMAT$(SystemDate.wMonth,  "00") & "/" & _
       FORMAT$(SystemDate.wDay,    "00") & " " & FORMAT$(SystemDate.wHour,   "00") & ":" & _
       FORMAT$(SystemDate.wMinute, "00") & ":" & FORMAT$(SystemDate.wSecond, "00") & " " & _
       "(" & FORMAT$(SystemDate.wMilliSeconds, "000") & " milliseconds) " & _
       CHOOSE$(SystemDate.wDayOfWeek + 1, "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
    
    END FUNCTION
    '______________________________________________________________________________
    
    FUNCTION PBMAIN()
     LOCAL CreationTime   AS FILETIME 'FILETIME is UTC
     LOCAL LastAccessTime AS FILETIME
     LOCAL LastWriteTime  AS FILETIME
     LOCAL zFileName      AS ASCIIZ * %MAX_PATH
     LOCAL FileNameLen    AS LONG
     LOCAL hFile          AS DWORD
    
     zFileName = FileNameGet(%HWND_DESKTOP, "","*", 0)
     IF LEN(zFileName) = 0 THEN
       MessageBox(%HWND_DESKTOP, "No file selected", "Filetime", %MB_ICONINFORMATION OR %MB_OK)
       EXIT FUNCTION
     END IF
    
     hFile = CreateFile(zFileName, %GENERIC_READ, %FILE_SHARE_READ, _ 'Get a file handle so we can query
                        BYVAL 0, %OPEN_EXISTING, %FILE_ATTRIBUTE_NORMAL, 0)
     IF hFile <> %INVALID_HANDLE_VALUE THEN 'Check if handle is valid
       GetFileTime(hFile, CreationTime, LastAccessTime, LastWriteTime) 'Get dates info
       MessageBox(%HWND_DESKTOP, zFileName          & $CRLF & $CRLF & _
                  "CreationTime"                            & $CRLF & _
                  GetDateTimeFormat(CreationTime)   & $CRLF & $CRLF & _
                  "LastAccessTime"                          & $CRLF & _
                  GetDateTimeFormat(LastAccessTime) & $CRLF & $CRLF & _
                  "LastWriteTime"                           & $CRLF & _
                  GetDateTimeFormat(LastWriteTime), _
                  "Time with mili-second and weekday", %MB_ICONINFORMATION OR %MB_OK)
       CloseHandle(hFile) 'Release handle clean-up
     END IF
    
    END FUNCTION
    '______________________________________________________________________________
    '
    Last edited by Pierre Bellisle; 8 Mar 2020, 12:07 AM.

    Comment


    • #3
      No API needed. Using plain PowerBASIC:
      Code:
      #COMPILE EXE
      #DIM ALL
      FUNCTION PBMAIN()
          LOCAL pt AS IPOWERTIME
          LOCAL strFile, strResult AS STRING
          LOCAL dird AS DIRDATA
          pt = CLASS "PowerTime"
      
      'Get file of interest
          DISPLAY OPENFILE 0, 100,100,"Select File",$NUL,$NUL,$NUL,$NUL , 0 TO strFile
          IF strFile = "" THEN
               ? "No file selected",,"File Times"
               EXIT FUNCTION
          END IF
          strResult = strFile & ":" & $CRLF & $CRLF
      
      'Get file details
          strFile = DIR$(strFile TO dird)
      
      'format file times
      pt.filetime = dird.CreationTime
      pt.ToLocalTime
      strResult += "CreationTime: " & pt.datestring & " " & pt.timestring
      
      pt.filetime = dird.LastAccessTime
      pt.ToLocalTime
      strResult += $CRLF & "LastAccesstime: " & pt.datestring & " " & pt.timestring
      
      pt.filetime = dird.LastWriteTime
      pt.ToLocalTime
      strResult += $CRLF & "LastWriteTime: " & pt.datestring & " " & pt.timestring
      
      'Display result
          ? strResult,,"File Times"
      END FUNCTION
      Note: Times displayed are local times, remove the pt.ToLocalTime lines to display as UTC

      Comment


      • #4
        Well... No API knowledge needed. No doubt that GetOpenFileName / FindFirstFile / FindClose are used under the hood.
        Interesting, I got 28,672 bytes for the exe vs 16,896 bytes for the same result exe via api. So it's probably also slower in a big file scanning process.

        Comment


        • #5
          Originally posted by Pierre Bellisle View Post
          Well... No API knowledge needed. No doubt that GetOpenFileName / FindFirstFile / FindClose are used under the hood.
          A bit pedantic?
          Even this humble application uses API under the hood.

          Code:
          Function PBMain() as Long
          ? Hello World"
          End Function
          OK, maybe I should have been more specific and said, "no API includes or direct API calls needed"

          Interesting, I got 28,672 bytes for the exe vs 16,896 bytes for the same result exe via api.
          Guess it depends on what win32api includes you are using for the api version
          With Jose's includes, I get 24,064 bytes
          With PB's includes, I get 13,824 bytes

          But since your API version doesn't allow the user to select a file, you're comparing apples to oranges.

          So it's probably also slower in a big file scanning process.
          That's a non-sequitur.

          Comment


          • #6
            > A bit pedantic?
            Absolutely not, some PowerBASIC function do not call any api, some does.
            A newbie will probably not be aware of that.

            > But since your API version doesn't allow the user to select a file, you're comparing apples to oranges.
            No, you did a bad assumption. The code I used to compare the exe size have the full GetOpenFileName() api called. With the "No file selected" messagebox, etc...
            Hence "the same result exe" I said above.

            Comment


            • #7
              Hey Friends.
              Sorry I donlt like the words "you Guys or Hey Guys"
              but I am a speed kind of guy.
              API or no API.
              Plus I. don't mean to disappoint.
              But I like compatibility unless a new function in a compiler adds value to some sort to my code. Yes, simplicity can be that at times to my liking.
              More than one method always helps in having options and you got love having options
              Last edited by Paul Purvis; 8 Mar 2020, 03:16 AM.
              p purvis

              Comment


              • #8
                Originally posted by Pierre Bellisle View Post
                > A bit pedantic?
                Absolutely not, some PowerBASIC function do not call any api, some does.
                A newbie will probably not be aware of that.
                A newbie probably won't care. Does it really matter that MessageBox "uses API"? . He will either use the intrinsic PB functions and statements quite happily. or subsequently learn to include win32api.inc and learn to use API calls directly.
                > But since your API version doesn't allow the user to select a file, you're comparing apples to oranges.
                No, you did a bad assumption. The code I used to compare the exe size have the full GetOpenFileName() api called. With the "No file selected" messagebox, etc..
                Hence "the same result exe" I said above.
                So your comparison code is not shown (i.e. unknown). Makes it a bit hard to compare

                Comment


                • #9
                  Thank you everyone, I'm very much appreciated your notes and advice here.

                  Comment


                  • #10
                    Glad if it's alright on your side Tim.

                    Comment


                    • #11
                      >A newbie probably won't care.

                      Well I won't think for the newbie, I guess some may care, some others may not.
                      For myself, I like to understand things, so, maybe other will to.
                      You are the one who came with "No API needed". and it could be misleading for some.

                      >Makes it a bit hard to compare..

                      You do not have to compare, I already did.
                      If you really want to do that, it is pretty easy, a few line of code to add.
                      You seem concerned, I did updated the code above...

                      Comment


                      • #12
                        Originally posted by Pierre Bellisle View Post
                        >A newbie probably won't care.

                        Well I won't think for the newbie, I guess some may care, some others may not.
                        For myself, I like to understand things, so, maybe other will to.
                        You are the one who came with "No API needed". and it could be misleading for some.

                        >Makes it a bit hard to compare..

                        You do not have to compare, I already did.
                        If you really want to do that, it is pretty easy, a few line of code to add.
                        You seem concerned, I did updated the code above...
                        27,136 bytes for your revised version with Jose's win32api.inc.

                        Comment


                        • #13
                          27,136 and 28,672 bytes.
                          A gain of more than 1500 bytes, it's pretty good on such a small exe.

                          Comment


                          • #14
                            If sector size is 2048, then 28672 is 14 sectors. My WAG is 27136 is actual bytes used for file. If file is increased to 28673, then sectors will be 15 or 30720 bytes.
                            Dale

                            Comment


                            • #15
                              Note: I hope nobody will stat another fruitless DDT-API war, on my side I use both a lot.

                              Hi Dale,
                              We can even go a little deeper by reading the pe header...

                              José includes --------------------------------------------
                              pe and lof() file size

                              LOF(hFile) = 27,136
                              Number of sections: 4
                              .text RawData : 23552, Pointer to raw data : 1024
                              .data RawData : 512, Pointer to raw data : 24576
                              .link RawData : 1536, Pointer to raw data : 25088
                              .rloc RawData : 512, Pointer to raw data : 26624
                              Name : .rloc
                              Rawsize: 27,136

                              LOF(hFile) = 28,672
                              Number of sections: 4
                              .text RawData : 23552, Pointer to raw data : 1024
                              .data RawData : 512, Pointer to raw data : 24576
                              .link RawData : 2560, Pointer to raw data : 25088
                              .rloc RawData : 1024, Pointer to raw data : 27648
                              Name : .rloc
                              Rawsize: 28,672

                              PowerBASIC includes --------------------------------------
                              pe and lof() file size

                              LOF(hFile) = 16,896
                              Number of sections: 4
                              .text RawData : 13312, Pointer to raw data : 1024
                              .data RawData : 512, Pointer to raw data : 14336
                              .link RawData : 1536, Pointer to raw data : 14848
                              .rloc RawData : 512, Pointer to raw data : 16384
                              Name : .rloc
                              Rawsize: 16,896

                              LOF(hFile) = 28,672
                              Number of sections: 4
                              .text RawData : 23552, Pointer to raw data : 1024
                              .data RawData : 512, Pointer to raw data : 24576
                              .link RawData : 2560, Pointer to raw data : 25088
                              .rloc RawData : 1024, Pointer to raw data : 27648
                              Name : .rloc
                              Rawsize: 28,672
                              ----------------------------------------------------------
                              -

                              Comment


                              • #16
                                I only noticed that 2nd number in post 13 was multiple of 2048, and difference between numbers was less than 2048.

                                I have no other comment or opinion re this thread.

                                Cheers,
                                Dale

                                Comment


                                • #17
                                  Hi Pierre, in your post#15 , what is the name of the application did you use to create those PE header results?
                                  It is interesting as you can see many parameters of the PE header.

                                  Comment


                                  • #18
                                    I think original code was from Semen Matusovski and Steven Pringels,
                                    I cant find it on the forum, here is my version...

                                    Code:
                                    #COMPILE EXE '#Win#
                                    #DIM ALL
                                    #INCLUDE "Win32api.inc"
                                    
                                    #BLOAT  1024 * 1024 * 4 'For test purpose
                                    '______________________________________________________________________________
                                    
                                    FUNCTION GetExePeInfo(szExeFileName AS STRING) AS STRING
                                     LOCAL pImageSectionHeader AS IMAGE_SECTION_HEADER POINTER
                                     LOCAL pImageDosHeader     AS IMAGE_DOS_HEADER POINTER
                                     LOCAL pImageNtHeaders     AS IMAGE_NT_HEADERS POINTER
                                     LOCAL pz                  AS STRINGZ POINTER
                                     LOCAL sInfo               AS STRING
                                     LOCAL sExeData            AS STRING
                                     LOCAL hFile               AS DWORD
                                     LOCAL RawSize             AS DWORD
                                     LOCAL Looper              AS LONG
                                    
                                     ERRCLEAR
                                     hFile = FREEFILE
                                     OPEN szExeFileName FOR BINARY SHARED AS #hFile
                                     IF ERR THEN
                                       FUNCTION = "Can not open file" : EXIT FUNCTION
                                     ELSE
                                       GET$ #hFile, LOF(hFile), sExeData
                                     END IF
                                     sInfo = "LOF(hFile) = " & FORMAT$(LOF(hFile), "#,") & " bytes" & $CRLF & $CRLF
                                     CLOSE #hFile
                                    
                                     pImageDosHeader = STRPTR(sExeData)
                                     IF LEN(sExeData) < SIZEOF(IMAGE_DOS_HEADER) THEN
                                       FUNCTION = "Size error" : EXIT FUNCTION
                                     END IF
                                    
                                     IF @pImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE THEN
                                       FUNCTION = "Magic error" : EXIT FUNCTION
                                     END IF
                                    
                                     IF LEN(sExeData) < @pImageDosHeader.e_lfanew + SIZEOF(IMAGE_NT_HEADERS) THEN
                                       FUNCTION = "Size error bis" : EXIT FUNCTION
                                     END IF
                                    
                                     pImageNtHeaders = pImageDosHeader + @pImageDosHeader.e_lfanew
                                    
                                     IF @pImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE THEN
                                       FUNCTION = "Signature error" : EXIT FUNCTION
                                     END IF
                                    
                                     IF (@pImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SIZEOF(@pImageNtHeaders.OptionalHeader)) OR _
                                       (@pImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC) THEN
                                       FUNCTION = "Optional magic error" : EXIT FUNCTION
                                     END IF
                                    
                                     IF @pImageNtHeaders.FileHeader.NumberOfSections < 1 THEN
                                       FUNCTION = "Section count error" : EXIT FUNCTION
                                     END IF
                                    
                                     pImageDosHeader     = STRPTR(sExeData)
                                     pImageNtHeaders     = pImageDosHeader + @pImageDosHeader.e_lfanew
                                     pImageSectionHeader = pImageNtHeaders + SIZEOF(IMAGE_NT_HEADERS)
                                    
                                     sInfo &= "Number of sections: " & FORMAT$(@pImageNtHeaders.FileHeader.NumberOfSections) & $CRLF
                                    
                                     FOR Looper = 0 TO @pImageNtHeaders.FileHeader.NumberOfSections - 1
                                        pz = VARPTR(@pImageSectionHeader[Looper].bName(0))
                                        sInfo &= @pz & "RawData :" & FORMAT$(@pImageSectionHeader[Looper].SizeOfRawData, "0,") & _
                                                 " bytes, Pointer to raw data: 0x" & Hex$(@pImageSectionHeader[Looper].PointerToRawData, 8) & $CRLF
                                       IF LEFT$(@pz, 5) = ".rloc" THEN
                                         rawsize = @pImageSectionHeader[Looper].PointerToRawData + _
                                                   @pImageSectionHeader[Looper].SizeOfRawData
                                         sInfo &= "Name   : " &  @pz  & $CRLF
                                         sInfo &= "Rawsize: " &  FORMAT$(Rawsize, "###,###") & $CRLF
                                       END IF
                                     NEXT
                                    
                                     FUNCTION = sInfo
                                    
                                    END FUNCTION
                                    '______________________________________________________________________________
                                    
                                    FUNCTION PBMAIN()
                                    
                                     GetExePeInfo(EXE.Full$)
                                     SLEEP 100 '
                                     MessageBox(%HWND_DESKTOP, GetExePeInfo(EXE.Full$) & $CRLF & "", "PE header", %MB_OK OR %MB_TOPMOST)
                                    
                                    END FUNCTION
                                    '______________________________________________________________________________
                                    '

                                    Comment


                                    • #19
                                      @ Dale,
                                      As you know, from Windows Explorer for a file propertie, you will have "Size" and "Size on disk".
                                      We also know that "Size on disk" is a disk cluster size multiple. And cluster are based on sector size.
                                      The "Size" is the real file size.
                                      For a .txt as example, it can be anything. 0, 1, 2,3,... whatever bytes.
                                      An .exe will have, due to the way it is made, a size based on many structures and parameters.

                                      Interesting stuff... PE Format

                                      Also interesting Microsoft support policy for 4K sector hard drives in Windows

                                      Comment


                                      • #20
                                        (I do not twitter, so @ is inapropriate )
                                        Dale

                                        Comment

                                        Working...
                                        X