diff --git a/.vscode/launch.json b/.vscode/launch.json index 4b9442f..f60ff10 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -258,6 +258,23 @@ "console": "externalTerminal", "stopAtEntry": false, "requireExactSource": false + }, + { + "name": "Set-Created-Date", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/Set-Created-Date/bin/Debug/net7.0/win-x64/Set-Created-Date.dll", + "args": [ + "s" + ], + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "cwd": "${workspaceFolder}", + "console": "externalTerminal", + "stopAtEntry": false, + "requireExactSource": false } ] } diff --git a/Copy-Distinct/Copy-Distinct.csproj b/Copy-Distinct/Copy-Distinct.csproj index d59b80c..ad0b7ce 100644 --- a/Copy-Distinct/Copy-Distinct.csproj +++ b/Copy-Distinct/Copy-Distinct.csproj @@ -9,7 +9,7 @@ d862524f-2b48-4f47-b4c3-5a8615814ec2 - Phares.View.by.Distance.Rename + Phares.View.by.Distance.Copy.Distinct false 7.0.101.1 Mike Phares @@ -45,9 +45,7 @@ - - diff --git a/Metadata/Models/Stateless/Methods/IMetadata.cs b/Metadata/Models/Stateless/Methods/IMetadata.cs index 80ab5f5..ce5f849 100644 --- a/Metadata/Models/Stateless/Methods/IMetadata.cs +++ b/Metadata/Models/Stateless/Methods/IMetadata.cs @@ -8,6 +8,11 @@ public interface IMetadata static DateTime? GetMinimumDateTime(IReadOnlyList directories) => Metadata.GetMinimumDateTime(directories); + DateTime? TestStatic_GetMinimumDateTime(IReadOnlyList directories, Shared.Models.FileHolder fileHolder) => + GetMinimumDateTime(directories, fileHolder); + static DateTime? GetMinimumDateTime(IReadOnlyList directories, Shared.Models.FileHolder fileHolder) => + Metadata.GetMinimumDateTime(directories, fileHolder); + string? TestStatic_GetModel(IReadOnlyList directories) => GetModel(directories); static string? GetModel(IReadOnlyList directories) => diff --git a/Metadata/Models/Stateless/Methods/Metadata.cs b/Metadata/Models/Stateless/Methods/Metadata.cs index ac24dbe..f7cae7d 100644 --- a/Metadata/Models/Stateless/Methods/Metadata.cs +++ b/Metadata/Models/Stateless/Methods/Metadata.cs @@ -93,6 +93,15 @@ internal class Metadata return result; } + internal static DateTime? GetMinimumDateTime(IReadOnlyList directories, Shared.Models.FileHolder fileHolder) + { + DateTime? result; + DateTime? dateTime = GetMinimumDateTime(directories); + List results = new() { fileHolder.CreationTime, fileHolder.LastWriteTime, dateTime }; + result = results.Min(); + return result; + } + internal static string? GetModel(IReadOnlyList directories) { string? result; diff --git a/Move-By-Id/MoveById.cs b/Move-By-Id/MoveById.cs index 8ee7fef..78dfd12 100644 --- a/Move-By-Id/MoveById.cs +++ b/Move-By-Id/MoveById.cs @@ -128,7 +128,7 @@ public class MoveById if (nameWithoutExtensionIsIdFormat) continue; } - (_, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); + (_, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, _PropertyConfiguration.PopulatePropertyId); if (id is null) continue; matches = (from l in allFiles where l.Contains($"{id}{fileHolder.ExtensionLowered}") select l).ToArray(); diff --git a/Rename/Rename.cs b/Rename/Rename.cs index ff5aaa2..455f274 100644 --- a/Rename/Rename.cs +++ b/Rename/Rename.cs @@ -281,7 +281,7 @@ public class Rename } } dateTimeFromName = Shared.Models.Stateless.Methods.IProperty.GetDateTimeFromName(fileHolder); - (dateTimeOriginal, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); + (dateTimeOriginal, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, _PropertyConfiguration.PopulatePropertyId); minimumDateTime = dateTimes.Min(); if (minimumDateTime is null) break; diff --git a/Set-Created-Date/Models/AppSettings.cs b/Set-Created-Date/Models/AppSettings.cs new file mode 100644 index 0000000..2bb9297 --- /dev/null +++ b/Set-Created-Date/Models/AppSettings.cs @@ -0,0 +1,32 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Set.Created.Date.Models; + +public class AppSettings +{ + + public string Company { init; get; } + public string CopyTo { init; get; } + public int MaxDegreeOfParallelism { init; get; } + public string WorkingDirectoryName { init; get; } + + [JsonConstructor] + public AppSettings(string company, + string copyTo, + int maxDegreeOfParallelism, + string workingDirectoryName) + { + Company = company; + CopyTo = copyTo; + MaxDegreeOfParallelism = maxDegreeOfParallelism; + WorkingDirectoryName = workingDirectoryName; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + +} \ No newline at end of file diff --git a/Set-Created-Date/Models/Binder/AppSettings.cs b/Set-Created-Date/Models/Binder/AppSettings.cs new file mode 100644 index 0000000..bd562be --- /dev/null +++ b/Set-Created-Date/Models/Binder/AppSettings.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.Configuration; +using System.Text.Json; + +namespace View_by_Distance.Set.Created.Date.Models.Binder; + +public class AppSettings +{ + +#nullable disable + + public string Company { get; set; } + public int? MaxDegreeOfParallelism { get; set; } + public string CopyTo { get; set; } + public string WorkingDirectoryName { get; set; } + +#nullable restore + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.AppSettings Get(AppSettings? appSettings) + { + Models.AppSettings result; + if (appSettings?.MaxDegreeOfParallelism is null) + throw new NullReferenceException(nameof(appSettings.MaxDegreeOfParallelism)); + result = new( + appSettings.Company, + appSettings.CopyTo, + appSettings.MaxDegreeOfParallelism.Value, + appSettings.WorkingDirectoryName + ); + return result; + } + + public static Models.AppSettings Get(IConfigurationRoot configurationRoot) + { + Models.AppSettings result; + AppSettings? appSettings = configurationRoot.Get(); + result = Get(appSettings); + return result; + } + +} \ No newline at end of file diff --git a/Set-Created-Date/Models/Binder/Configuration.cs b/Set-Created-Date/Models/Binder/Configuration.cs new file mode 100644 index 0000000..0f479c3 --- /dev/null +++ b/Set-Created-Date/Models/Binder/Configuration.cs @@ -0,0 +1,59 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using System.ComponentModel.DataAnnotations; +using System.Text.Json; + +namespace View_by_Distance.Set.Created.Date.Models.Binder; + +public class Configuration +{ + +#nullable disable + + [Display(Name = "Ignore Extensions"), Required] public string[] IgnoreExtensions { get; set; } + [Display(Name = "Property Configuration"), Required] public Property.Models.Configuration PropertyConfiguration { get; set; } + [Display(Name = "Person Birthday Format"), Required] public string PersonBirthdayFormat { get; set; } + +#nullable restore + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + private static Models.Configuration Get(Configuration? configuration) + { + Models.Configuration result; + if (configuration is null) + throw new NullReferenceException(nameof(configuration)); + if (configuration.IgnoreExtensions is null) + throw new NullReferenceException(nameof(configuration.IgnoreExtensions)); + if (configuration.PersonBirthdayFormat is null) + throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat)); + result = new( + configuration.IgnoreExtensions, + configuration.PersonBirthdayFormat, + configuration.PropertyConfiguration); + return result; + } + + public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, Property.Models.Configuration propertyConfiguration) + { + Models.Configuration result; + Configuration? configuration; + if (isEnvironment is null) + configuration = configurationRoot.Get(); + else + { + string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment); + string section = string.Concat(environmentName, ":", nameof(Configuration)); + IConfigurationSection configurationSection = configurationRoot.GetSection(section); + configuration = configurationSection.Get(); + } + result = Get(configuration); + result.SetAndUpdate(propertyConfiguration); + return result; + } + +} \ No newline at end of file diff --git a/Set-Created-Date/Models/Configuration.cs b/Set-Created-Date/Models/Configuration.cs new file mode 100644 index 0000000..4c65693 --- /dev/null +++ b/Set-Created-Date/Models/Configuration.cs @@ -0,0 +1,38 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace View_by_Distance.Set.Created.Date.Models; + +public class Configuration +{ + + protected Property.Models.Configuration _PropertyConfiguration; + public string[] IgnoreExtensions { init; get; } + public string PersonBirthdayFormat { init; get; } + + public Property.Models.Configuration PropertyConfiguration => _PropertyConfiguration; + + [JsonConstructor] + public Configuration( + string[] ignoreExtensions, + string personBirthdayFormat, + Property.Models.Configuration propertyConfiguration) + { + IgnoreExtensions = ignoreExtensions; + PersonBirthdayFormat = personBirthdayFormat; + _PropertyConfiguration = propertyConfiguration; + } + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); + return result; + } + + public void SetAndUpdate(Property.Models.Configuration configuration) + { + _PropertyConfiguration = configuration; + _PropertyConfiguration.Update(); + } + +} \ No newline at end of file diff --git a/Set-Created-Date/Models/Stateless/SerilogExtensionMethods.cs b/Set-Created-Date/Models/Stateless/SerilogExtensionMethods.cs new file mode 100644 index 0000000..c346274 --- /dev/null +++ b/Set-Created-Date/Models/Stateless/SerilogExtensionMethods.cs @@ -0,0 +1,10 @@ +namespace View_by_Distance.Set.Created.Date.Models.Stateless; + +public static class SerilogExtensionMethods +{ + + internal static void Warn(this Serilog.ILogger log, string messageTemplate) => log.Warning(messageTemplate); + + internal static void Info(this Serilog.ILogger log, string messageTemplate) => log.Information(messageTemplate); + +} \ No newline at end of file diff --git a/Set-Created-Date/Program.cs b/Set-Created-Date/Program.cs new file mode 100644 index 0000000..73764a2 --- /dev/null +++ b/Set-Created-Date/Program.cs @@ -0,0 +1,71 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using System.Diagnostics; +using System.Reflection; +using View_by_Distance.Set.Created.Date.Models; +using View_by_Distance.Shared.Models.Stateless.Methods; + +namespace View_by_Distance.Set.Created.Date; + +public class Program +{ + + public static void Secondary(List args) + { + LoggerConfiguration loggerConfiguration = new(); + Assembly assembly = Assembly.GetExecutingAssembly(); + bool debuggerWasAttachedAtLineZero = Debugger.IsAttached || assembly.Location.Contains(@"\bin\Debug"); + IsEnvironment isEnvironment = new(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: debuggerWasAttachedAtLineZero, nullASPNetCoreEnvironmentIsProduction: !debuggerWasAttachedAtLineZero); + IConfigurationBuilder configurationBuilder = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile(isEnvironment.AppSettingsFileName, optional: false, reloadOnChange: true) + .AddUserSecrets(); + IConfigurationRoot configurationRoot = configurationBuilder.Build(); + AppSettings appSettings = Models.Binder.AppSettings.Get(configurationRoot); + if (appSettings.MaxDegreeOfParallelism > Environment.ProcessorCount) + throw new Exception("MaxDegreeOfParallelism must be =< Environment.ProcessorCount!"); + if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) + throw new Exception("Working directory name must have a value!"); + string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assembly.GetName().Name, appSettings.WorkingDirectoryName); + Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory); + _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, configurationRoot); + Log.Logger = loggerConfiguration.CreateLogger(); + ILogger log = Log.ForContext(); + int silentIndex = args.IndexOf("s"); + if (silentIndex > -1) + args.RemoveAt(silentIndex); + try + { + if (args is null) + throw new Exception("args is null!"); + Shared.Models.Console console = new(); + _ = new SetCreatedDate(args, isEnvironment, configurationRoot, appSettings, workingDirectory, silentIndex > -1, console); + } + catch (Exception ex) + { + log.Fatal(string.Concat(ex.Message, Environment.NewLine, ex.StackTrace)); + } + finally + { + Log.CloseAndFlush(); + } + if (silentIndex > -1) + log.Debug("Done. Bye"); + else + { + log.Debug("Done. Press 'Enter' to end"); + _ = Console.ReadLine(); + } + } + + public static void Main(string[] args) + { + if (args is not null) + Secondary(args.ToList()); + else + Secondary(new List()); + } + +} \ No newline at end of file diff --git a/Set-Created-Date/Set-Created-Date.csproj b/Set-Created-Date/Set-Created-Date.csproj new file mode 100644 index 0000000..1ed598a --- /dev/null +++ b/Set-Created-Date/Set-Created-Date.csproj @@ -0,0 +1,59 @@ + + + enable + 10.0 + enable + Exe + win-x64 + net7.0 + b3bbcc69-1439-4e86-9bbf-75c8e8839cc0 + + + Phares.View.by.Distance.Set.Created.Date + false + 7.0.101.1 + Mike Phares + Phares + true + snupkg + + + true + true + true + + + Windows + + + OSX + + + Linux + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + \ No newline at end of file diff --git a/Set-Created-Date/SetCreatedDate.cs b/Set-Created-Date/SetCreatedDate.cs new file mode 100644 index 0000000..24b8726 --- /dev/null +++ b/Set-Created-Date/SetCreatedDate.cs @@ -0,0 +1,165 @@ +using Microsoft.Extensions.Configuration; +using Phares.Shared; +using Serilog; +using ShellProgressBar; +using View_by_Distance.Set.Created.Date.Models; +using View_by_Distance.Shared.Models; +using View_by_Distance.Shared.Models.Methods; + +namespace View_by_Distance.Set.Created.Date; + +public class SetCreatedDate +{ + + private readonly AppSettings _AppSettings; + private readonly string _WorkingDirectory; + private readonly Configuration _Configuration; + private readonly IsEnvironment _IsEnvironment; + private readonly IConfigurationRoot _ConfigurationRoot; + private readonly IReadOnlyDictionary _FileGroups; + private readonly Property.Models.Configuration _PropertyConfiguration; + + public SetCreatedDate(List args, IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, AppSettings appSettings, string workingDirectory, bool isSilent, IConsole console) + { + if (isSilent) + { } + if (console is null) + { } + _AppSettings = appSettings; + _IsEnvironment = isEnvironment; + _WorkingDirectory = workingDirectory; + _ConfigurationRoot = configurationRoot; + ILogger? log = Log.ForContext(); + Property.Models.Configuration propertyConfiguration = Property.Models.Binder.Configuration.Get(isEnvironment, configurationRoot); + string[] directories = new string[] { propertyConfiguration.ResultContent }; + _FileGroups = Shared.Models.Stateless.Methods.IPath.GetKeyValuePairs(propertyConfiguration, appSettings.CopyTo, directories); + Configuration configuration = Models.Binder.Configuration.Get(isEnvironment, configurationRoot, propertyConfiguration); + _PropertyConfiguration = propertyConfiguration; + _Configuration = configuration; + propertyConfiguration.Update(); + log.Information(propertyConfiguration.RootDirectory); + Verify(); + List lines = SetCreatedDateFilesInDirectories(log); + File.WriteAllLines($"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv", lines); + if (!lines.Any()) + _ = Shared.Models.Stateless.Methods.IPath.DeleteEmptyDirectories(propertyConfiguration.RootDirectory); + } + + private void Verify() + { + if (_AppSettings is null) + { } + if (_IsEnvironment is null) + { } + if (_Configuration is null) + { } + if (_ConfigurationRoot is null) + { } + if (_WorkingDirectory is null) + { } + if (_PropertyConfiguration is null) + { } + } + + private static (List, List) Get(List filesCollection) + { + List results = new(); + string? directory; + List directories = new(); + foreach (string[] files in filesCollection) + { + if (!files.Any()) + continue; + directory = Path.GetDirectoryName(files.First()); + if (directory is null) + continue; + if (!directories.Contains(directory)) + directories.Add(directory); + results.AddRange(files); + } + return (directories, results); + } + + private List<(FileHolder, DateTime)> GetToDoCollection(ProgressBar progressBar, FileHolder[] fileHolders) + { + List<(FileHolder, DateTime)> results = new(); + int? id; + string? message; + DateTime? dateTime; + DateTime?[] dateTimes; + bool isIgnoreExtension; + DateTime? dateTimeOriginal; + bool isValidImageFormatExtension; + foreach (FileHolder fileHolder in fileHolders) + { + progressBar.Tick(); + if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null) + continue; + if (_PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered)) + continue; + isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered); + isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered); + if (isIgnoreExtension || !isValidImageFormatExtension) + continue; + (dateTimeOriginal, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, _PropertyConfiguration.PopulatePropertyId); + dateTime = dateTimeOriginal is not null ? dateTimeOriginal : dateTime = dateTimes.Min(); + if (dateTime is null) + continue; + if (dateTime.Value == fileHolder.CreationTime) + continue; + results.Add((fileHolder, dateTime.Value)); + } + return results; + } + + private static List SetCreatedDateForeach(ProgressBar progressBar, List<(FileHolder, DateTime)> toDoCollection) + { + List results = new(); + foreach ((FileHolder fileHolder, DateTime dateTime) in toDoCollection) + { + progressBar.Tick(); + results.Add(fileHolder.NameWithoutExtension); + try + { File.SetCreationTime(fileHolder.FullName, dateTime); } + catch (Exception) { } + } + return results; + } + + private List SetCreatedDateFilesInDirectories(ILogger log) + { + List results = new(); + ProgressBar progressBar; + ConsoleKey? consoleKey = null; + const string fileSearchFilter = "*"; + string message = nameof(SetCreatedDate); + const string directorySearchFilter = "*"; + List filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter); + (_, List allFiles) = Get(filesCollection); + ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }; + progressBar = new(allFiles.Count, message, options); + FileHolder[] fileHolders = (from l in allFiles select new FileHolder(l)).ToArray(); + List<(FileHolder, DateTime)> toDoCollection = GetToDoCollection(progressBar, fileHolders); + progressBar.Dispose(); + log.Information($"Ready to set created date {toDoCollection.Count} file(s)?"); + for (int y = 0; y < int.MaxValue; y++) + { + log.Information("Press \"Y\" key to set created date file(s), \"N\" key to log file(s) or close console to not set created date files"); + consoleKey = System.Console.ReadKey().Key; + if (consoleKey is ConsoleKey.Y or ConsoleKey.N) + break; + } + log.Information(". . ."); + if (consoleKey is null || consoleKey.Value != ConsoleKey.Y) + log.Information("Nothing set!"); + else + { + progressBar = new(allFiles.Count, message, options); + results.AddRange(SetCreatedDateForeach(progressBar, toDoCollection)); + progressBar.Dispose(); + log.Information("Done setting created date"); + } + return results; + } + +} \ No newline at end of file diff --git a/Set-Created-Date/appsettings.Development.json b/Set-Created-Date/appsettings.Development.json new file mode 100644 index 0000000..ad9619a --- /dev/null +++ b/Set-Created-Date/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Log4netProvider": "Debug" + } + }, + "Serilog": { + "MinimumLevel": "Debug" + } +} \ No newline at end of file diff --git a/Set-Created-Date/appsettings.json b/Set-Created-Date/appsettings.json new file mode 100644 index 0000000..cda8ada --- /dev/null +++ b/Set-Created-Date/appsettings.json @@ -0,0 +1,128 @@ +{ + "ComparePathsFile": "", + "Company": "Mike Phares", + "CopyTo": "", + "Linux": {}, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Log4netProvider": "Debug", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "MaxDegreeOfParallelism": 6, + "Serilog": { + "Using": [ + "Serilog.Sinks.Console", + "Serilog.Sinks.File" + ], + "MinimumLevel": "Information", + "WriteTo": [ + { + "Name": "Debug", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "Console", + "Args": { + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "%workingDirectory% - Log/log-.txt", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{MethodName}) ({InstanceId}) ({RemoteIpAddress}) {Message}{NewLine}{Exception}", + "rollingInterval": "Hour" + } + } + ], + "Enrich": [ + "FromLogContext", + "WithMachineName", + "WithThreadId" + ], + "Properties": { + "Application": "Sample" + } + }, + "WorkingDirectoryName": "PharesApps", + "Windows": { + "Configuration": { + "DateGroup": "1e85c0ba", + "DiffPropertyDirectory": "", + "FileNameDirectorySeparator": ".Z.", + "ForcePropertyLastWriteTimeToCreationTime": false, + "MaxImagesInDirectoryForTopLevelFirstPass": 10, + "OutputExtension": ".jpg", + "Pattern": "[^ABCDEFGHIJKLMNOPQRSTUVWXYZbcdfghjklmnpqrstvwxyz0-9]", + "PersonBirthdayFormat": "yyyy-MM-dd_HH", + "PopulatePropertyId": true, + "PropertiesChangedForProperty": false, + "ResultAllInOne": "_ _ _", + "ResultAllInOneSubdirectoryLength": 2, + "ResultCollection": "[]", + "ResultContent": "()", + "ResultSingleton": "{}", + "RootDirectory": "D:/Images", + "WriteBitmapDataBytes": false, + "IgnoreExtensions": [ + ".gif", + ".GIF", + ".nef", + ".NEF", + ".pdf", + ".PDF" + ], + "ValidImageFormatExtensions": [ + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".png", + ".PNG", + ".tiff", + ".TIFF", + ".tif", + ".TIF" + ], + "ValidMetadataExtensions": [ + ".3gp", + ".3GP", + ".avi", + ".AVI", + ".bmp", + ".BMP", + ".gif", + ".GIF", + ".ico", + ".ICO", + ".jpeg", + ".JPEG", + ".jpg", + ".JPG", + ".m4v", + ".M4V", + ".mov", + ".MOV", + ".mp4", + ".MP4", + ".mta", + ".MTA", + ".png", + ".PNG", + ".tiff", + ".TIFF", + ".tif", + ".TIF" + ] + } + } +} \ No newline at end of file diff --git a/Shared/Models/Stateless/Methods/IProperty.cs b/Shared/Models/Stateless/Methods/IProperty.cs index f3364ff..dbe696f 100644 --- a/Shared/Models/Stateless/Methods/IProperty.cs +++ b/Shared/Models/Stateless/Methods/IProperty.cs @@ -46,10 +46,10 @@ public interface IProperty static (bool?, string[]) IsWrongYear(Models.FileHolder fileHolder, DateTime? dateTimeOriginal, List dateTimes) => Property.IsWrongYear(fileHolder, dateTimeOriginal, dateTimes); - (DateTime?, DateTime?[], int?, string?) TestStatic_Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) => - Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); - static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) => - Property.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension); + (DateTime?, DateTime?[], int?, string?) TestStatic_Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, bool populateId) => + Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, populateId); + static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, bool populateId) => + Property.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, populateId); DateTime? TestStatic_GetDateTimeFromName(Models.FileHolder fileHolder) => GetDateTimeFromName(fileHolder); diff --git a/Shared/Models/Stateless/Methods/Property.cs b/Shared/Models/Stateless/Methods/Property.cs index 9dcb7a0..80c4632 100644 --- a/Shared/Models/Stateless/Methods/Property.cs +++ b/Shared/Models/Stateless/Methods/Property.cs @@ -390,7 +390,7 @@ internal abstract class Property #pragma warning disable CA1416 - internal static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension) + internal static (DateTime?, DateTime?[], int?, string?) Get(Models.FileHolder fileHolder, bool isIgnoreExtension, bool isValidImageFormatExtension, bool populateId) { int? id = null; string? message = null; @@ -409,16 +409,21 @@ internal abstract class Property ASCIIEncoding asciiEncoding = new(); string dateTimeFormat = IProperty.DateTimeFormat(); using Image image = Image.FromFile(fileHolder.FullName); - using Bitmap bitmap = new(image); - Rectangle rectangle = new(0, 0, image.Width, image.Height); - BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat); - IntPtr intPtr = bitmapData.Scan0; - int length = bitmapData.Stride * bitmap.Height; - bytes = new byte[length]; - Marshal.Copy(intPtr, bytes, 0, length); - bitmap.UnlockBits(bitmapData); - id = IProperty.GetDeterministicHashCode(bytes); - bitmap.Dispose(); + if (!populateId) + id = null; + else + { + using Bitmap bitmap = new(image); + Rectangle rectangle = new(0, 0, image.Width, image.Height); + BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat); + IntPtr intPtr = bitmapData.Scan0; + int length = bitmapData.Stride * bitmap.Height; + bytes = new byte[length]; + Marshal.Copy(intPtr, bytes, 0, length); + bitmap.UnlockBits(bitmapData); + id = IProperty.GetDeterministicHashCode(bytes); + bitmap.Dispose(); + } if (image.PropertyIdList.Contains((int)IExif.Tags.DateTime)) { propertyItem = image.GetPropertyItem((int)IExif.Tags.DateTime); diff --git a/View-by-Distance-MKLink-Console.sln b/View-by-Distance-MKLink-Console.sln index 8ba6163..f5ee58b 100644 --- a/View-by-Distance-MKLink-Console.sln +++ b/View-by-Distance-MKLink-Console.sln @@ -51,6 +51,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rename", "Rename\Rename.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Resize", "Resize\Resize.csproj", "{27D0D869-394D-4B07-83DF-2095B16026FC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Set-Created-Date", "Set-Created-Date\Set-Created-Date.csproj", "{B067643E-9F59-46A1-A001-ACF4661F059C}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{B4FB6B43-36EC-404D-B934-5C695C6E32CC}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsWithFaceRecognitionDotNet", "TestsWithFaceRecognitionDotNet\TestsWithFaceRecognitionDotNet.csproj", "{A67D73C7-A1A1-4443-B681-776339CFA08A}" @@ -184,5 +186,9 @@ Global {E08CB662-FF25-48DF-A378-A770E1EFBA56}.Debug|Any CPU.Build.0 = Debug|Any CPU {E08CB662-FF25-48DF-A378-A770E1EFBA56}.Release|Any CPU.ActiveCfg = Release|Any CPU {E08CB662-FF25-48DF-A378-A770E1EFBA56}.Release|Any CPU.Build.0 = Release|Any CPU + {B067643E-9F59-46A1-A001-ACF4661F059C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B067643E-9F59-46A1-A001-ACF4661F059C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B067643E-9F59-46A1-A001-ACF4661F059C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B067643E-9F59-46A1-A001-ACF4661F059C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal