DriveMonitor.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.IO.Enumeration;
  5. using System.Linq;
  6. using System.Threading;
  7. using System.Xml.Linq;
  8. namespace Ips.Library.Basic
  9. {
  10. public class DriveMonitor
  11. {
  12. public DriveMonitor()
  13. {
  14. }
  15. public DriveMonitor(string monitorPaths, double minFreePercent = 0.2, double clearPercent = 0.2)
  16. {
  17. MonitorPaths = monitorPaths;
  18. MinFreePercent = minFreePercent;
  19. _rootPaths = MonitorPaths.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList();
  20. }
  21. public string MonitorPaths { get; private set; }
  22. public double MinFreePercent { get; private set; }
  23. public double ClearPercent { get; private set; }
  24. public List<string> RootPaths => _rootPaths;
  25. private List<string> _rootPaths;
  26. Timer _clearTimer;
  27. volatile bool _isRunning = false;
  28. public virtual void Start()
  29. {
  30. if (_isRunning) Stop();
  31. _clearTimer = new Timer(DoWork, null, 1000, Timeout.Infinite);
  32. _isRunning = true;
  33. }
  34. public virtual void Stop()
  35. {
  36. _isRunning = false;
  37. _clearTimer?.Change(Timeout.Infinite, Timeout.Infinite);
  38. _clearTimer?.Dispose();
  39. _clearTimer = null;
  40. }
  41. protected virtual void DoWork(object obj)
  42. {
  43. try
  44. {
  45. var monitorDrives = _rootPaths.GroupBy(m => Path.GetPathRoot(m));
  46. foreach (var driveDirGroup in monitorDrives)
  47. {
  48. DriveInfo driveInfo = new DriveInfo(driveDirGroup.Key);
  49. if (driveInfo.DriveType != DriveType.Fixed) continue;
  50. var freePercent = GetDriveFreePercent(driveInfo);
  51. while (freePercent < MinFreePercent)
  52. {
  53. ClearDrive(driveInfo, driveDirGroup.ToList());
  54. freePercent = GetDriveFreePercent(driveInfo);
  55. }
  56. }
  57. }
  58. catch (Exception ex)
  59. {
  60. IpsLogger.Warn($"执行文件清理失败",ex);
  61. }
  62. finally
  63. {
  64. _clearTimer.Change(1000 * 60, Timeout.Infinite);
  65. }
  66. }
  67. protected virtual void ClearDrive(DriveInfo driveInfo, List<string> dirs)
  68. {
  69. if (dirs == null || dirs.Count == 0) return;
  70. var fileInfoList = dirs.Where(m => Directory.Exists(m))
  71. .SelectMany(m => Directory.GetFiles(m, "*", SearchOption.AllDirectories))
  72. .Select(m => new FileInfo(m))
  73. .OrderBy(m => m.LastWriteTime)
  74. .ToList();
  75. List<string> fileDirs = new List<string>();
  76. foreach (var fileItem in fileInfoList)
  77. {
  78. try
  79. {
  80. if (fileItem.DirectoryName.IsNotNullOrWhitespace())
  81. fileDirs.AddIfNotContains(fileItem.DirectoryName);
  82. fileItem.Delete();
  83. }
  84. catch (Exception ex)
  85. {
  86. IpsLogger.Warn($"删除【{fileItem.FullName}】失败",ex);
  87. }
  88. if (GetDriveFreePercent(driveInfo) > MinFreePercent + ClearPercent) break;
  89. }
  90. foreach (var fileDir in fileDirs)
  91. {
  92. try
  93. {
  94. bool hasFile = Directory.EnumerateFiles(fileDir, "*", SearchOption.AllDirectories).Any();
  95. if (!hasFile)
  96. {
  97. DirectoryUtil.DeleteIfExists(fileDir);
  98. }
  99. }
  100. catch (Exception ex)
  101. {
  102. IpsLogger.Warn($"清理空目录【{fileDir}】出错",ex);
  103. }
  104. }
  105. }
  106. protected virtual float GetDriveFreePercent(DriveInfo driveInfo)
  107. {
  108. return driveInfo.AvailableFreeSpace * 1.0f / driveInfo.TotalSize;
  109. }
  110. }
  111. }