using Newtonsoft.Json; using Quartz; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WIDESEAWCS_BasicInfoRepository; using WIDESEAWCS_BasicInfoService; using WIDESEAWCS_IBasicInfoRepository; using WIDESEAWCS_ISystemRepository; using WIDESEAWCS_ISystemServices; using WIDESEAWCS_ITaskInfoRepository; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_QuartzJob.Repository; using WIDESEAWCS_QuartzJob.Service; using WIDESEAWCS_SignalR; namespace WIDESEAWCS_Tasks { [DisallowConcurrentExecution] public partial class CommonDeleteLogJob : JobBase, IJob { private readonly ISys_DelLogRepository _logRepository; public CommonDeleteLogJob(ISys_DelLogRepository logRepository) { _logRepository = logRepository; } public Task Execute(IJobExecutionContext context) { try { Task.Run(() => { while (true) { try { var logfileName = _logRepository.QueryData(x => true); foreach (var item in logfileName) { string folderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, item.FileName); DateTime intervalTime = DateTime.Now.AddDays(-item.IntervalTime); CleanDirectory(folderPath, intervalTime); } Thread.Sleep(1000 * 60 * 60 * 24); } catch { Thread.Sleep(1000 * 60 * 60); } } }); return Task.CompletedTask; } catch (Exception) { throw; } } public static void CleanDirectory(string rootPath, DateTime cutoffDate, bool deleteEmptyDirs = true) { var rootDir = new DirectoryInfo(rootPath); ValidateRootDirectory(rootDir); CleanDirectoryRecursive(rootDir, cutoffDate, deleteEmptyDirs); } private static void CleanDirectoryRecursive(DirectoryInfo dir, DateTime cutoffDate, bool deleteEmptyDirs) { foreach (var item in dir.GetFileSystemInfos()) { if (item is FileInfo file) { if (file.LastWriteTime < cutoffDate) { DeleteWithRetry(file.FullName, maxRetries: 5); } } else if (item is DirectoryInfo subDir) { CleanDirectoryRecursive(subDir, cutoffDate, deleteEmptyDirs); } } if (deleteEmptyDirs && dir.LastWriteTime < cutoffDate && !dir.EnumerateFileSystemInfos().Any()) { try { if (IsRootDirectory(dir)) { Console.WriteLine($"跳过根目录删除: {dir.FullName}"); return; } dir.Delete(true); Console.WriteLine($"已删除空目录: {dir.FullName}"); } catch (Exception ex) when (ex is UnauthorizedAccessException or IOException) { Console.WriteLine($"无法删除目录: {dir.FullName} | 错误: {ex.Message}"); } } } private static void DeleteWithRetry(string path, int maxRetries) { for (int i = 0; i <= maxRetries; i++) { try { if (File.Exists(path)) { File.Delete(path); } else if (Directory.Exists(path)) { Directory.Delete(path, true); } break; } catch (IOException ex) when (ex.HResult == -2147024894) // 文件被占用 { if (i == maxRetries) throw; Thread.Sleep(100); } catch { if (i == maxRetries) throw; Thread.Sleep(50); } } } private static void ValidateRootDirectory(DirectoryInfo dir) { if (!dir.Exists) throw new DirectoryNotFoundException($"目录不存在: {dir.FullName}"); if (IsSystemDirectory(dir)) throw new InvalidOperationException("禁止清理系统目录"); } private static bool IsSystemDirectory(DirectoryInfo dir) => dir.FullName.Contains("System32", StringComparison.OrdinalIgnoreCase) || dir.FullName.Contains("ProgramData", StringComparison.OrdinalIgnoreCase); private static bool IsRootDirectory(DirectoryInfo dir) => Path.GetPathRoot(dir.FullName) == dir.FullName; } }