using System; using System.Collections.Generic; using System.IO; using System.IO.Enumeration; using System.Linq; using System.Threading; using System.Xml.Linq; namespace Ips.Library.Basic { public class DriveMonitor { public DriveMonitor() { } public DriveMonitor(string monitorPaths, double minFreePercent = 0.2, double clearPercent = 0.2) { MonitorPaths = monitorPaths; MinFreePercent = minFreePercent; _rootPaths = MonitorPaths.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList(); } public string MonitorPaths { get; private set; } public double MinFreePercent { get; private set; } public double ClearPercent { get; private set; } public List RootPaths => _rootPaths; private List _rootPaths; Timer _clearTimer; volatile bool _isRunning = false; public virtual void Start() { if (_isRunning) Stop(); _clearTimer = new Timer(DoWork, null, 1000, Timeout.Infinite); _isRunning = true; } public virtual void Stop() { _isRunning = false; _clearTimer?.Change(Timeout.Infinite, Timeout.Infinite); _clearTimer?.Dispose(); _clearTimer = null; } protected virtual void DoWork(object obj) { try { var monitorDrives = _rootPaths.GroupBy(m => Path.GetPathRoot(m)); foreach (var driveDirGroup in monitorDrives) { DriveInfo driveInfo = new DriveInfo(driveDirGroup.Key); if (driveInfo.DriveType != DriveType.Fixed) continue; var freePercent = GetDriveFreePercent(driveInfo); while (freePercent < MinFreePercent) { ClearDrive(driveInfo, driveDirGroup.ToList()); freePercent = GetDriveFreePercent(driveInfo); } } } catch (Exception ex) { IpsLogger.Warn($"执行文件清理失败",ex); } finally { _clearTimer.Change(1000 * 60, Timeout.Infinite); } } protected virtual void ClearDrive(DriveInfo driveInfo, List dirs) { if (dirs == null || dirs.Count == 0) return; var fileInfoList = dirs.Where(m => Directory.Exists(m)) .SelectMany(m => Directory.GetFiles(m, "*", SearchOption.AllDirectories)) .Select(m => new FileInfo(m)) .OrderBy(m => m.LastWriteTime) .ToList(); List fileDirs = new List(); foreach (var fileItem in fileInfoList) { try { if (fileItem.DirectoryName.IsNotNullOrWhitespace()) fileDirs.AddIfNotContains(fileItem.DirectoryName); fileItem.Delete(); } catch (Exception ex) { IpsLogger.Warn($"删除【{fileItem.FullName}】失败",ex); } if (GetDriveFreePercent(driveInfo) > MinFreePercent + ClearPercent) break; } foreach (var fileDir in fileDirs) { try { bool hasFile = Directory.EnumerateFiles(fileDir, "*", SearchOption.AllDirectories).Any(); if (!hasFile) { DirectoryUtil.DeleteIfExists(fileDir); } } catch (Exception ex) { IpsLogger.Warn($"清理空目录【{fileDir}】出错",ex); } } } protected virtual float GetDriveFreePercent(DriveInfo driveInfo) { return driveInfo.AvailableFreeSpace * 1.0f / driveInfo.TotalSize; } } }