Search code examples
c#datetimekernel32interopservicessafehandle

How to get creation DateTime of file from very long path?


I have file paths which are very long, so can be handled only using SafeFileHandle.
Want to get creation datetime.
When tried getting millies and then converted in DateTime then it is 1600 years less.

Code:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool GetFileTime(SafeFileHandle hFile, ref long lpCreationTime, ref long lpLastAccessTime, ref long lpLastWriteTime);

void fnc(String file){
    var filePath = @"\\?\" + file;
    var fileObj = CreateFile(filePath, Constants.SafeFile.GENERIC_READ, 0, IntPtr.Zero, Constants.SafeFile.OPEN_EXISTING, 0, IntPtr.Zero);
    long millies = 0, l1 = 0, l2 = 0;

    if(GetFileTime(fileObj, ref millies, ref l1, ref l2))
    {
        DateTime creationTime = new DateTime(millies, DateTimeKind.Local);

Above creationTime is 1600 years less. Instead of year 2019, its 0419.

Then I had to do this

        DateTime creationTime = new DateTime(millies, DateTimeKind.Local).AddYears(1600);
    }
}

Above creationTime is correct as I have added 1600 years.

What makes date 1600 years less?
Am I doing anything wrong?


Solution

  • The FILETIME structure returned by GetFileTime returns the number of 100 nanosecond intervals starting from January 1st 1601. You can see the documentation for this here: Microsoft docs

    Rather than adding 1600 years there is a built in .net function that converts for you - DateTime.FromFileTime(). In your example the code would be:

    if (GetFileTime(fileObj, ref millies, ref l1, ref l2))
    {
        DateTime creationTime = DateTime.FromFileTime(millies);
    }
    

    I would also change the variable name from millies as that is a bit misleading (GetFileTime does not return milliseconds).