// See https://aka.ms/new-console-template for more information using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; internal class ChecksumWorkerConfig { public string Directory { get; set; } = "."; public string Extension { get; set; } = "*"; } internal class ChecksumWorker : BackgroundService { private readonly SHA512 SHA = SHA512.Create(); private readonly ChecksumWorkerConfig _config; private readonly ILogger _classLogger; public ChecksumWorker(IOptions options, ILogger classLogger) { _config = options.Value; _classLogger = classLogger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var dateTime = DateTime.Now; var directory = _config.Directory; var extension = _config.Extension; if (Directory.Exists(directory) == false) { _classLogger.LogError($"Directory {directory} does not exist"); return; } _classLogger.LogInformation($"Watch in: {directory}"); _classLogger.LogInformation($"Watch for: {extension}"); while (stoppingToken.IsCancellationRequested == false) { var items = Directory.GetFiles(directory, extension) .Select(file => new { time = File.GetLastWriteTime(file), file = file, }) .Where(x => x.time > dateTime) .OrderBy(x => x.time); foreach (var item in items) { var fileTime = item.time; if (fileTime > dateTime) { if (await TryCalculateChecksumAsync(item.file) is { } checksum) { _classLogger.LogInformation($"File {item.file} has changed {checksum}", checksum); } else { break; // try again later } } dateTime = fileTime; } await Task.Delay(1000, stoppingToken); } } private async Task TryCalculateChecksumAsync(string file) { try { using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)) { var checksum = await SHA.ComputeHashAsync(fs); return Convert.ToBase64String(checksum); } } catch { return default; } } }