(C#) Timestomp by Jean-Pierre LESUEUR

Created the Tuesday 09 August 2022. Updated 1 month, 3 weeks ago.

Description:

This tiny code snippet demonstrate the principle of file time stomping.

Steps:

  • Enumerate files in current directory (excluding the target file).
  • Sort enumerated files by modification date.
  • Takes the most recent file and apply its File Creation Date, File Last Modification and File Last Access to our target file.

Additional information:

  • Supports relative target file.
  • If no files lives inside the current directory, then current directory (parent folder) date information are used.
  • If no files lives inside the current directory and current directory is a root path, then timestomp procedure fails.

Code

            using System;
using System.IO;

void timeStomp(String targetFile)
{
    targetFile = Path.GetFullPath(targetFile);

    if (!File.Exists(targetFile))
    {
        throw new FileNotFoundException(String.Format("File \"{0}\" does not exists.", targetFile));
    }

    string? parentDirectory = Path.GetDirectoryName(targetFile);
    bool isInRoot = false;

    if (parentDirectory == null)
    {
        parentDirectory = Directory.GetDirectoryRoot(targetFile);
        isInRoot = true;
    }

    var options = new EnumerationOptions()
    {
        IgnoreInaccessible = true,
        RecurseSubdirectories = true,
        AttributesToSkip = FileAttributes.System | FileAttributes.Hidden,
    };

    var candidates = new DirectoryInfo(parentDirectory)
        .GetFiles("*.*", options)
        .Where(file => !file.FullName.Equals(targetFile, StringComparison.OrdinalIgnoreCase))
        .OrderByDescending(file => file.LastWriteTime)
        .ToList();

    FileInfo? candidate = null;    
    
    if (candidates.Count > 0)
    {
        candidate = candidates.First();
    }   
    else if (!isInRoot)
    {
        candidate = new FileInfo(parentDirectory);
    }

    if (candidate != null)
    {
        Console.WriteLine(string.Format("Using \"{0}\" file for timeStomping...", candidate));

        File.SetCreationTime(targetFile, candidate.CreationTime);
        File.SetLastAccessTime(targetFile, candidate.LastAccessTime);
        File.SetLastWriteTime(targetFile, candidate.LastWriteTime);

        Console.WriteLine("Done.");
    }
    else
    {
       throw new Exception("Could not find suitable existing file for timeStomping...");
    }
}

timeStomp("G:\\test\\sub7.exe");