Repository: Cryolitia/PhotoTimeFix Branch: main Commit: d51d3ed7aefa Files: 34 Total size: 144.1 KB Directory structure: gitextract_d81n_rbi/ ├── .gitignore ├── PhotoTimeFix/ │ ├── App.xaml │ ├── App.xaml.cs │ ├── PhotoTimeFix.csproj │ ├── Properties/ │ │ └── launchSettings.json │ ├── Resource/ │ │ ├── Resource.Designer.cs │ │ ├── Resource.resx │ │ ├── Resource.zh-Hans.resx │ │ └── Resource.zh-Hant.resx │ ├── Util/ │ │ ├── DefaultFileProcessor.cs │ │ ├── FileExistValidationRule.cs │ │ ├── IFileProcessor.cs │ │ ├── ProcessResult.cs │ │ ├── ProcessResultList.cs │ │ ├── SettingItemAttribute.cs │ │ └── ThemeHelper.cs │ ├── ViewBinding/ │ │ ├── MainWindowBinding.cs │ │ └── SettingBinding.cs │ ├── Window/ │ │ ├── CodeEditWindow.xaml │ │ ├── CodeEditWindow.xaml.cs │ │ ├── ImageWindow.xaml │ │ ├── ImageWindow.xaml.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── ProcessBarWindow.xaml │ │ ├── ProcessBarWindow.xaml.cs │ │ ├── ProcessWindow.xaml │ │ └── ProcessWindow.xaml.cs │ └── app.manifest ├── PhotoTimeFix.sln ├── README.md └── WapProject/ ├── .gitignore ├── Package.appxmanifest └── WapProject.wapproj ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.rsuser *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_h.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *_wpftmp.csproj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush personal settings .cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ # Local History for Visual Studio .localhistory/ *.pfx ================================================ FILE: PhotoTimeFix/App.xaml ================================================  ================================================ FILE: PhotoTimeFix/App.xaml.cs ================================================ using System; using System.Globalization; using System.Threading.Tasks; using System.Windows; using Microsoft.AppCenter; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; namespace PhotoTimeFix { /// /// Interaction logic for App.xaml /// public partial class App : Application { #if DEBUG public static readonly bool IsDebug = true; #else public static readonly bool IsDebug = false; #endif protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); if (!IsDebug) { //UI线程未捕获异常处理事件 DispatcherUnhandledException += (sender, e1) => { MessageBox.Show(e1.Exception.Message); Crashes.TrackError(e1.Exception); }; //Task线程内未捕获异常处理事件 TaskScheduler.UnobservedTaskException += (sender, e1) => { MessageBox.Show(e1.Exception.Message); Crashes.TrackError(e1.Exception); }; //非UI线程未捕获异常处理事件 AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs args) { var ex = args.ExceptionObject; if (ex is Exception) { MessageBox.Show((ex as Exception).Message); Crashes.TrackError(ex as Exception); } }; //System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US"); //System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); var countryCode = RegionInfo.CurrentRegion.TwoLetterISORegionName; AppCenter.SetCountryCode(countryCode); AppCenter.Start("5aa5aa14-0bd1-45f1-bea4-72d960c9c576", typeof(Crashes), typeof(Analytics)); } } } } ================================================ FILE: PhotoTimeFix/PhotoTimeFix.csproj ================================================  WinExe net48 true True a9ikq-xzp6j-001.ico PhotoTimeFix.App Cryolitia Github https://github.com/Cryolitia/PhotoTimeFix Copyright 2018-Now Cryolitia README.md 照片时间修复.jpg https://github.com/Cryolitia/PhotoTimeFix true false ..\cert.pfx disable README.md AnyCPU true 1.3.3 en;zh-Hans;zh-Hant app.manifest 1.3.3 embedded true True \ cert.pfx True \ M2.NSudo.dll True True Resource.resx True True Resource.resx PublicResXFileCodeGenerator Resource.Designer.cs PublicResXFileCodeGenerator PublicResXFileCodeGenerator PublicResXFileCodeGenerator Resource.Designer.cs PublicResXFileCodeGenerator PublicResXFileCodeGenerator Always Always Always Always Always Always Always ================================================ FILE: PhotoTimeFix/Properties/launchSettings.json ================================================ { "profiles": { "PhotoTimeFix": { "commandName": "Project" } } } ================================================ FILE: PhotoTimeFix/Resource/Resource.Designer.cs ================================================ //------------------------------------------------------------------------------ // // 此代码由工具生成。 // 运行时版本:4.0.30319.42000 // // 对此文件的更改可能会导致不正确的行为,并且如果 // 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ namespace PhotoTimeFix.Resource { using System; /// /// 一个强类型的资源类,用于查找本地化的字符串等。 /// // 此类是由 StronglyTypedResourceBuilder // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resource { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resource() { } /// /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PhotoTimeFix.Resource.Resource", typeof(Resource).Assembly); resourceMan = temp; } return resourceMan; } } /// /// 重写当前线程的 CurrentUICulture 属性,对 /// 使用此强类型资源类的所有资源查找执行重写。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } /// /// 查找类似 Author: 的本地化字符串。 /// public static string About_Author { get { return ResourceManager.GetString("About_Author", resourceCulture); } } /// /// 查找类似 Cryolitia 的本地化字符串。 /// public static string About_Neuron { get { return ResourceManager.GetString("About_Neuron", resourceCulture); } } /// /// 查找类似 Open Source License 的本地化字符串。 /// public static string About_OpenSourceLicense { get { return ResourceManager.GetString("About_OpenSourceLicense", resourceCulture); } } /// /// 查找类似 Github repo: 的本地化字符串。 /// public static string About_OpenSourceLink { get { return ResourceManager.GetString("About_OpenSourceLink", resourceCulture); } } /// /// 查找类似 Telegram: 的本地化字符串。 /// public static string About_Telegram { get { return ResourceManager.GetString("About_Telegram", resourceCulture); } } /// /// 查找类似 Thanks to all open source software contributors for going forward 的本地化字符串。 /// public static string About_ThanksToOpenSource { get { return ResourceManager.GetString("About_ThanksToOpenSource", resourceCulture); } } /// /// 查找类似 Photo Time Fix 的本地化字符串。 /// public static string App_Name { get { return ResourceManager.GetString("App_Name", resourceCulture); } } /// /// 查找类似 Compile 的本地化字符串。 /// public static string CodeEditWindow_Compile { get { return ResourceManager.GetString("CodeEditWindow_Compile", resourceCulture); } } /// /// 查找类似 Compiled successfully 的本地化字符串。 /// public static string CodeEditWindow_CompileSuccess { get { return ResourceManager.GetString("CodeEditWindow_CompileSuccess", resourceCulture); } } /// /// 查找类似 Current creation time: 的本地化字符串。 /// public static string MainWindow_CurrentCreationTime { get { return ResourceManager.GetString("MainWindow_CurrentCreationTime", resourceCulture); } } /// /// 查找类似 Current last write time: 的本地化字符串。 /// public static string MainWindow_CurrentModificationTime { get { return ResourceManager.GetString("MainWindow_CurrentModificationTime", resourceCulture); } } /// /// 查找类似 Current user: 的本地化字符串。 /// public static string MainWindow_CurrentUser { get { return ResourceManager.GetString("MainWindow_CurrentUser", resourceCulture); } } /// /// 查找类似 Current user group: 的本地化字符串。 /// public static string MainWindow_CurrentUserGroup { get { return ResourceManager.GetString("MainWindow_CurrentUserGroup", resourceCulture); } } /// /// 查找类似 Custom filename parser 的本地化字符串。 /// public static string MainWindow_CustomFileProcessingClass { get { return ResourceManager.GetString("MainWindow_CustomFileProcessingClass", resourceCulture); } } /// /// 查找类似 File Name 的本地化字符串。 /// public static string MainWindow_FileName { get { return ResourceManager.GetString("MainWindow_FileName", resourceCulture); } } /// /// 查找类似 File System Metadata 的本地化字符串。 /// public static string MainWindow_FileSystem { get { return ResourceManager.GetString("MainWindow_FileSystem", resourceCulture); } } /// /// 查找类似 File or folder path 的本地化字符串。 /// public static string MainWindow_FolderFilePath { get { return ResourceManager.GetString("MainWindow_FolderFilePath", resourceCulture); } } /// /// 查找类似 New Time: 的本地化字符串。 /// public static string MainWIndow_NewTime { get { return ResourceManager.GetString("MainWIndow_NewTime", resourceCulture); } } /// /// 查找类似 Run As Admin 的本地化字符串。 /// public static string MainWindow_RunAsAdmin { get { return ResourceManager.GetString("MainWindow_RunAsAdmin", resourceCulture); } } /// /// 查找类似 Run As Trust Installer 的本地化字符串。 /// public static string MainWindow_RunAsTrustInstaller { get { return ResourceManager.GetString("MainWindow_RunAsTrustInstaller", resourceCulture); } } /// /// 查找类似 Start 的本地化字符串。 /// public static string MainWindow_Start { get { return ResourceManager.GetString("MainWindow_Start", resourceCulture); } } /// /// 查找类似 Open Log File 的本地化字符串。 /// public static string ProcessWindow_Copy { get { return ResourceManager.GetString("ProcessWindow_Copy", resourceCulture); } } /// /// 查找类似 Detail 的本地化字符串。 /// public static string ProcessWindow_Detail { get { return ResourceManager.GetString("ProcessWindow_Detail", resourceCulture); } } /// /// 查找类似 File 的本地化字符串。 /// public static string ProcessWindow_File { get { return ResourceManager.GetString("ProcessWindow_File", resourceCulture); } } /// /// 查找类似 New Time 的本地化字符串。 /// public static string ProcessWindow_NewTime { get { return ResourceManager.GetString("ProcessWindow_NewTime", resourceCulture); } } /// /// 查找类似 Status 的本地化字符串。 /// public static string ProcessWindow_Status { get { return ResourceManager.GetString("ProcessWindow_Status", resourceCulture); } } /// /// 查找类似 Path should not be empty 的本地化字符串。 /// public static string Rule_PathNonNull { get { return ResourceManager.GetString("Rule_PathNonNull", resourceCulture); } } /// /// 查找类似 Path not exist 的本地化字符串。 /// public static string Rule_PathNotExist { get { return ResourceManager.GetString("Rule_PathNotExist", resourceCulture); } } /// /// 查找类似 Process only media files 的本地化字符串。 /// public static string Setting_MediaOnly { get { return ResourceManager.GetString("Setting_MediaOnly", resourceCulture); } } /// /// 查找类似 Only process files with MIME type "image/*" or "video/*" when batch processing 的本地化字符串。 /// public static string Setting_MediaOnlySummary { get { return ResourceManager.GetString("Setting_MediaOnlySummary", resourceCulture); } } /// /// 查找类似 Open media 的本地化字符串。 /// public static string Setting_OpenMedia { get { return ResourceManager.GetString("Setting_OpenMedia", resourceCulture); } } /// /// 查找类似 Prefer EXIF 的本地化字符串。 /// public static string Setting_PreferExif { get { return ResourceManager.GetString("Setting_PreferExif", resourceCulture); } } /// /// 查找类似 Try to read EXIF tag firstly 的本地化字符串。 /// public static string Setting_PreferExifSummary { get { return ResourceManager.GetString("Setting_PreferExifSummary", resourceCulture); } } /// /// 查找类似 Safe mode 的本地化字符串。 /// public static string Setting_SafeMode { get { return ResourceManager.GetString("Setting_SafeMode", resourceCulture); } } /// /// 查找类似 Prevent time from being set before 1970 or after the current time 的本地化字符串。 /// public static string Setting_SafeModeSummary { get { return ResourceManager.GetString("Setting_SafeModeSummary", resourceCulture); } } /// /// 查找类似 Save Log file 的本地化字符串。 /// public static string Setting_SaveLog { get { return ResourceManager.GetString("Setting_SaveLog", resourceCulture); } } /// /// 查找类似 This operation will attempt to manipulate the file itself and write the EXIF ​​tag, which may cause irrecoverable damage to the file. Please back up before proceeding! 的本地化字符串。 /// public static string Warning_EXIF { get { return ResourceManager.GetString("Warning_EXIF", resourceCulture); } } } } ================================================ FILE: PhotoTimeFix/Resource/Resource.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Author: Cryolitia Open Source License Github repo: Thanks to all open source software contributors for going forward Photo Time Fix Compile Current creation time: Current last write time: Current user: Current user group: Custom filename parser File or folder path New Time: Run As Admin Run As Trust Installer Start Path should not be empty Path not exist Telegram: Safe mode Compiled successfully File Status New Time Detail Prevent time from being set before 1970 or after the current time Prefer EXIF Try to read EXIF tag firstly Process only media files Only process files with MIME type "image/*" or "video/*" when batch processing Open media Open Log File Save Log file File Name File System Metadata This operation will attempt to manipulate the file itself and write the EXIF ​​tag, which may cause irrecoverable damage to the file. Please back up before proceeding! ================================================ FILE: PhotoTimeFix/Resource/Resource.zh-Hans.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 照片时间修复 文件或文件夹路径 当前创建时间 当前修改时间 新时间: 自定义文件名解析方法 开始 当前用户: 当前用户组: 以管理员权限运行 以Trust Installer权限运行 作者: 神经元/Cryolitia 开源地址: 开放源代码许可 感谢所有开源软件的贡献者们的一往无前 编译 路径不应为空 路径不存在 安全模式 编译成功 文件 状态 新时间 细节 阻止将时间设置为1970年之前或当前时间之后 EXIF优先 优先尝试读取EXIF信息 仅处理媒体文件 批处理时仅处理MIME类型为"image/*"或"video/*"的文件 打开媒体 打开日志文件 保存日志文件 文件名 文件系统元数据 该操作会尝试操作文件本身并写入EXIF标签,可能造成文件不可恢复的损坏,请先备份再进行操作! ================================================ FILE: PhotoTimeFix/Resource/Resource.zh-Hant.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 照片時間修復 檔案或資料夾路徑 當前建立時間 當前修改時間 新時間: 自定義檔名解析方法 開始 當前使用者: 當前使用者組: 以管理員許可權執行 以Trust Installer許可權執行 作者: 神經元/Cryolitia 開源地址: 開放原始碼許可 感謝所有開源軟體的貢獻者們的一往無前 編譯 路徑不應為空 路徑不存在 安全模式 編譯成功 檔案 狀態 新時間 細節 阻止將時間設定為1970年之前或當前時間之後 EXIF優先 優先嚐試讀取EXIF資訊 僅處理媒體檔案 批處理時僅處理MIME型別為"image/*"或"video/*"的檔案 開啟媒體 開啟日誌檔案 儲存日誌檔案 檔案名稱 檔案系統元資料 該操作會嘗試操作檔案本身並寫入EXIF標籤,可能造成檔案不可恢復的損壞,請先備份再進行操作! ================================================ FILE: PhotoTimeFix/Util/DefaultFileProcessor.cs ================================================ using System; using System.Globalization; using System.IO; using System.Text.RegularExpressions; using PhotoTimeFix.Util; public class DefaultFileProcessor : IFileProcessor { private const string regexString = "(19|20)[0-9]{2}[^0-9]*?(0[1-9]|1[0-2])[^0-9]*?([0-2][0-9]|[3][0-1])[^0-9]*?([01][0-9]|2[0-3])[^0-9]*?[0-5][0-9][^0-9]*?[0-5][0-9]"; private static Regex regex = new Regex(regexString, RegexOptions.Compiled); private static Regex regex2 = new Regex(@"\d{13}", RegexOptions.Compiled); private static Regex regex3 = new Regex(@"\d{10}", RegexOptions.Compiled); private static Regex spaceRemover = new Regex(@"\D+", RegexOptions.Compiled); public DateTime? GetFileDateTime(FileInfo fileInfo) { var mathch = regex.Match(fileInfo.Name); if (mathch.Success) { string result = mathch.Value; result = spaceRemover.Replace(result, ""); return DateTime.ParseExact(result, "yyyyMMddHHmmss", CultureInfo.InvariantCulture); } else { var match2 = regex2.Match(fileInfo.Name); Int64 result2 = -1; if (match2.Success) { result2 = Int64.Parse(match2.Value)/1000; } else { var match3 = regex3.Match(fileInfo.Name); if (match3.Success) { result2 = Int64.Parse(match3.Value); } } if (result2!=-1) { return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(result2); } else { return null; } } } } ================================================ FILE: PhotoTimeFix/Util/FileExistValidationRule.cs ================================================ using System.Globalization; using System.IO; using System.Windows.Controls; namespace PhotoTimeFix.Util { public class FileExistValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { if (value == null || string.IsNullOrWhiteSpace((value ?? "").ToString())) return new ValidationResult(false, Resource.Resource.Rule_PathNonNull); var path = value.ToString(); return File.Exists(path) || Directory.Exists(path) ? ValidationResult.ValidResult : new ValidationResult(false, Resource.Resource.Rule_PathNotExist); } } } ================================================ FILE: PhotoTimeFix/Util/IFileProcessor.cs ================================================ using System; using System.IO; namespace PhotoTimeFix.Util { public interface IFileProcessor { DateTime? GetFileDateTime(FileInfo fileInfo); } } ================================================ FILE: PhotoTimeFix/Util/ProcessResult.cs ================================================ namespace PhotoTimeFix.Util { public class ProcessResult { public ProcessResult(string mFileName, string mDateTime, string mStatus, string mDetail) { FileName = mFileName; DateTime = mDateTime; Status = mStatus; Detail = mDetail; } public string FileName { get; set; } public string DateTime { get; set; } public string Status { get; set; } public string Detail { get; set; } } } ================================================ FILE: PhotoTimeFix/Util/ProcessResultList.cs ================================================ using System.Collections.ObjectModel; namespace PhotoTimeFix.Util { public class ProcessResultList : ObservableCollection { public void Add(string mFileName, string mDateTime, string mStatus, string mDetail) { Add(new ProcessResult(mFileName, mDateTime, mStatus, mDetail)); } } } ================================================ FILE: PhotoTimeFix/Util/SettingItemAttribute.cs ================================================ using System; using System.Windows.Forms; namespace PhotoTimeFix.Util { [AttributeUsage(AttributeTargets.Property)] public class SettingItemAttribute : Attribute { public SettingItemAttribute(string name, string summary) { Name = name; Summary = summary; } public SettingItemAttribute(string res) { try { Name = typeof(Resource.Resource).GetProperty("Setting_" + res).GetValue(null) as string; } catch (Exception e) { MessageBox.Show(e.Message); } try { Summary = typeof(Resource.Resource).GetProperty("Setting_" + res+ "Summary").GetValue(null) as string; } catch (Exception e) { //ignore } } public string Name { get; set; } public string Summary { get; set; } } } ================================================ FILE: PhotoTimeFix/Util/ThemeHelper.cs ================================================ using System; using System.Text; using System.Windows; using System.Windows.Media; using Windows.Foundation.Metadata; using Windows.UI.ViewManagement; using MaterialDesignThemes.Wpf; using Microsoft.Win32; namespace PhotoTimeFix.Util { public static class ThemeHelper { private static bool eventInitial; //https://kira-96.github.io/posts/%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96Windows10%E4%B8%BB%E9%A2%98%E9%A2%9C%E8%89%B2/ public static void InitTheme() { var paletteHelper = new PaletteHelper(); var isLight = true; try { var registryValue = Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", null); isLight = Convert.ToBoolean(registryValue); } catch (Exception exception) { MessageBox.Show(exception.ToString()); } var theme = new Theme(); if (isLight) theme.SetLightTheme(); else theme.SetDarkTheme(); var color = isLight ? Color.FromRgb(66, 133, 244) : Color.FromRgb(130, 168, 231); theme.SetPrimaryColor(color); RequireSystemTheme(theme, isLight); if (!eventInitial) { SystemEvents.UserPreferenceChanged += (sender, args) => { InitTheme(); }; eventInitial = true; } paletteHelper.SetTheme(theme); } public static void RequireSystemTheme(Theme theme, bool isLight) { try { #pragma warning disable CA1416 // 验证平台兼容性 if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.UISettings")) { var uiSettings = new UISettings(); var accentColor = uiSettings.GetColorValue(UIColorType.Accent); theme.SetPrimaryColor(Color.FromRgb(accentColor.R, accentColor.G, accentColor.B)); theme.SetSecondaryColor(Color.FromRgb(accentColor.R, accentColor.G, accentColor.B)); if (!isLight) { theme.Cards.Background = Color.FromRgb(18, 18, 18); theme.Background = Colors.Black; } } #pragma warning restore CA1416 // 验证平台兼容性 } catch (Exception e) { MessageBox.Show(e.ToString()); } } public static void ShowSystemColor() { var uiSettings = new UISettings(); var builder = new StringBuilder(); builder.Append("System Colors: " + '\n'); foreach (UIColorType type in Enum.GetValues(typeof(UIColorType))) if (type != UIColorType.Complement) builder.Append(type + ": " + uiSettings.GetColorValue(type) + '\n'); builder.Append('\n'); foreach (UIElementType type in Enum.GetValues(typeof(UIElementType))) builder.Append(type + ": " + uiSettings.UIElementColor(type) + '\n'); System.Windows.Forms.MessageBox.Show(builder.ToString()); } } } ================================================ FILE: PhotoTimeFix/ViewBinding/MainWindowBinding.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Windows; using CSScriptLib; using ICSharpCode.AvalonEdit.Document; using PhotoTimeFix.Util; namespace PhotoTimeFix.ViewBinding { public class MainWindowBinding : INotifyPropertyChanged { private IEnumerable _detailTags; private string _filePath; private IFileProcessor _fileProcessor; private TextDocument _fileProcessorCode; private Visibility _isFile = Visibility.Collapsed; private DateTime? _nowDate; private DateTime? _nowTime; private Visibility _pathExist = Visibility.Collapsed; public bool IsDebug => App.IsDebug; public string FilePath { get => _filePath; set { _filePath = value; OnPropertyChanged(nameof(FilePath)); } } public Visibility IsFile { get => _isFile; set { _isFile = value; OnPropertyChanged(nameof(IsFile)); OnPropertyChanged(nameof(StartEnabled)); } } public Visibility PathExist { get => _pathExist; set { _pathExist = value; OnPropertyChanged(nameof(PathExist)); OnPropertyChanged(nameof(StartEnabled)); } } public IEnumerable DetailTags { get => _detailTags; set { _detailTags = value; OnPropertyChanged(nameof(DetailTags)); } } public DateTime? NowDate { get => _nowDate; set { _nowDate = value; OnPropertyChanged(nameof(NowDate)); OnPropertyChanged(nameof(StartEnabled)); } } public DateTime? NowTime { get => _nowTime; set { _nowTime = value; OnPropertyChanged(nameof(NowTime)); OnPropertyChanged(nameof(StartEnabled)); } } public bool StartEnabled => NowDate != null && NowTime != null && IsFile == Visibility.Visible || IsFile == Visibility.Collapsed && PathExist == Visibility.Visible; public TextDocument FileProcessorCode { get { if (_fileProcessorCode == null) { var assembly = Assembly.GetExecutingAssembly(); var stream = assembly.GetManifestResourceStream(assembly.GetName().Name + ".Util.DefaultFileProcessor.cs"); var reader = new StreamReader(stream); _fileProcessorCode = new TextDocument(reader.ReadToEnd()); _fileProcessorCode.SetOwnerThread(Application.Current.Dispatcher.Thread); } return _fileProcessorCode; } set { _fileProcessorCode = value; OnPropertyChanged(nameof(FileProcessorCode)); } } public IFileProcessor FileProcessor { get { if (_fileProcessor == null) { var code = Application.Current.Dispatcher.Invoke(() => FileProcessorCode.Text); _fileProcessor = (IFileProcessor) CSScript.Evaluator.LoadCode(code); } return _fileProcessor; } set => _fileProcessor = value; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } ================================================ FILE: PhotoTimeFix/ViewBinding/SettingBinding.cs ================================================ using System.ComponentModel; using System.Runtime.CompilerServices; using PhotoTimeFix.Util; namespace PhotoTimeFix.ViewBinding { public class SettingBinding : INotifyPropertyChanged { private bool _onlyMedia = true; private bool _safetyMode = true; private bool _showMedia = false; private bool _saveLog = false; [SettingItem("SafeMode")] public bool SafetyMode { get => _safetyMode; set { _safetyMode = value; OnPropertyChanged(nameof(SafetyMode)); } } [SettingItem("MediaOnly")] public bool OnlyMedia { get => _onlyMedia; set { _onlyMedia = value; OnPropertyChanged(nameof(OnlyMedia)); } } [SettingItem("OpenMedia")] public bool ShowMedia { get => _showMedia; set { _showMedia = value; OnPropertyChanged(nameof(ShowMedia)); } } [SettingItem("SaveLog")] public bool SaveLog { get => _saveLog; set { _saveLog = value; OnPropertyChanged(nameof(SaveLog)); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } ================================================ FILE: PhotoTimeFix/Window/CodeEditWindow.xaml ================================================