Question 156

Comment déterminer la date de création, modification, ou de dernier accès d'un fichier ?

L'une des méthodes les plus simples pour déterminer la date de dernière modification d'un fichier est d'utiliser la fonction built-in FileDateTime :

    Debug.Print FileDateTime("c:\autoexec.bat")  

Cependant, dans de nombreux cas, il peut être nécessaire de différencier date de création, de dernière modification et de dernier accès à un fichier. Les APIs Windows fournissent une panoplie de fonctions permettant l'accès à ces informations. Nous décrirons ci après rapidement leur usage. Ensuite, nous construirons ensuite un exemple complet qui vous permettra de récupérer les dates à des fins d'affichage.

La fonction GetFileTime est très certainement la première des fonctions à décrire. Celle-ci renvoie les trois informations précédemment citées, ayant pour entrée le seul un hFile, qui peut être acquis assez facilement. Le problème se situe dans le format de description de la date et heure : il s'agit d'une structure FILETIME, représentant une date UTC sur 64 bits.

Bien qu'après quelques calculs une telle valeur pourrait être interprétée, les APIs Windows peuvent une fois de plus faciliter la tâche. Ainsi, la fonction FileTimeToLocalFileTime sera utilisée afin de convertir l'heure UTC en heure locale. Cette dernière est en effet la forme la plus susceptible d'être comprise par l'utilisateur. A noter la fonction FileDateTime retourne elle aussi l'heure corespondant au fuseau horraire utilisé. La forme UTC sera elle utilisée lorsque des comparaisons de dates, sur deux systèmes différents, doivent être effectuées. En effet, la date UTC n'est pas perturbée par des phénomènes tels que le passage de l'heure d'hiver à l'heure d'été.

C'est enfin au tour de la fonction FileTimeToSystemTime d'entrer en jeu. Celle-ci nous permettra d'effectuer la séparation de la date, encore à ce stade représentée comme une valeur 64 bits, en différentes composantes mieux connues des utilisateurs, telles que le jour, l'année, l'heure, etc.

Voyons maintenant par un exemple comment utiliser ces fonctions dans la pratique :

Private Const GENERIC_READ = &H80000000
Private Const FILE_SHARE_READ = &H1
Private Const OPEN_EXISTING = 3
Private Const INVALID_HANDLE_VALUE = -1

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

Private Declare Function GetFileTime _
    Lib "kernel32" _
    ( _
    ByVal hfile As Long, _
    lpCreationTime As Any, _
    lpLastAccessTime As Any, _
    lpLastWriteTime As Any _
    ) _
    As Long
Private Declare Function FileTimeToSystemTime _
    Lib "kernel32" _
    ( _
    lpFileTime As FILETIME, _
    lpSystemTime As SYSTEMTIME _
    ) _
    As Long
Private Declare Function CreateFile _
    Lib "kernel32" _
    Alias "CreateFileA" _
    ( _
    ByVal lpFileName As String, _
    ByVal dwDesiredAccess As Long, _
    ByVal dwShareMode As Long, _
    lpSecurityAttributes As Any, _
    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 LocalFileTimeToFileTime _
    Lib "kernel32" _
    ( _
    lpLocalFileTime As FILETIME, _
    lpFileTime As FILETIME _
    ) _
    As Long
Private Declare Function FileTimeToLocalFileTime _
    Lib "kernel32" _
    ( _
    lpFileTime As FILETIME, _
    lpLocalFileTime As FILETIME _
    ) _
    As Long

Function GetFileCreationTime(FilePath As String) As Date
    Dim hfile As Long
    Dim fileCreationTime As FILETIME
    Dim sysCreationTime As SYSTEMTIME
    Dim fileLocalTime As FILETIME

    'Dans un premier temps, nous acquierons un hfile sur le fichier désiré
    hfile = CreateFile( _
        FilePath & vbNullChar, _
        GENERIC_READ, _
        FILE_SHARE_READ, _
        ByVal 0&, _
        OPEN_EXISTING, _
        0, _
        0)

    If hfile <> INVALID_HANDLE_VALUE Then
        'On récupère ensuite l'heure de création du fichier.  
        'Les autres dates importantes sont obtenues de manière similaire en choisissant le(s) paramètre(s) retourné(s)
        If GetFileTime(hfile, _
            fileCreationTime, _
            ByVal 0&, _
            ByVal 0& _
            ) Then

            'La date UTC est convertie en date locale
            If FileTimeToLocalFileTime( _
                fileCreationTime, _
                fileLocalTime _
                ) Then

                'On récupère les différentes composantes de la date
                If FileTimeToSystemTime( _
                    fileLocalTime, _
                    sysCreationTime _
                    ) Then

                    'On retrouve un objet Date, plus simple à manipuler en VB
                    GetFileCreationTime = DateSerial( _
                        sysCreationTime.wYear, _
                        sysCreationTime.wMonth, _
                        sysCreationTime.wDay _
                        ) _
                        + _
                        TimeSerial( _
                        sysCreationTime.wHour, _
                        sysCreationTime.wMinute, _
                        sysCreationTime.wSecond _
                        )
                End If
            End If
        End If

        'Ne pas oublier de fermer un fichier ouvert!
        CloseHandle hfile
    End If
End Function


Pour aller plus loin

Date de publication : 25 février 2007
Dernière modification : 25 février 2007
Rubriques : Déploiement, Fichiers & dossiers
Mots-clés : date, heure, jour, année, mois, création, modification, accès, temps, FileDateTime, UTC, filetime