Quick.FileMonitor.pas 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. { ***************************************************************************
  2. Copyright (c) 2015-2019 Kike Pérez
  3. Unit : Quick.FileMonitor
  4. Description : Watch for single file changes
  5. Author : Kike Pérez
  6. Version : 1.2
  7. Created : 11/09/2017
  8. Modified : 29/01/2019
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.FileMonitor;
  22. interface
  23. {$i QuickLib.inc}
  24. uses
  25. Classes,
  26. {$IFDEF MSWINDOWS}
  27. Windows,
  28. SyncObjs,
  29. {$ELSE}
  30. SyncObjs,
  31. {$ENDIF}
  32. SysUtils,
  33. {$IFDEF FPC}
  34. Quick.Files;
  35. {$ELSE}
  36. System.IOUtils;
  37. {$ENDIF}
  38. type
  39. TMonitorNotify = (mnNone, mnFileCreated, mnFileModified, mnFileDeleted);
  40. TMonitorWatch = set of TMonitorNotify;
  41. TFileChangeNotify = procedure(MonitorNofify : TMonitorNotify) of object;
  42. TFileMonitor = class(TThread)
  43. private
  44. fFileName : string;
  45. fTickEvent : TSimpleEvent;
  46. fInterval : Integer;
  47. fNotifies : TMonitorWatch;
  48. fEnabled : Boolean;
  49. fExists : Boolean;
  50. fModifedDate : TDateTime;
  51. fCurrentMonitorNotify : TMonitorNotify;
  52. fOnChangeNotify : TFileChangeNotify;
  53. procedure SetEnabled(Status : Boolean);
  54. procedure NotifyEvent;
  55. protected
  56. procedure Execute; override;
  57. public
  58. constructor Create;
  59. destructor Destroy; override;
  60. property FileName : string read fFileName write fFileName;
  61. property Interval : Integer read fInterval write fInterval;
  62. property Notifies : TMonitorWatch read fNotifies write fNotifies;
  63. property OnFileChange : TFileChangeNotify read fOnChangeNotify write fOnChangeNotify;
  64. property Enabled : Boolean read fEnabled write SetEnabled;
  65. end;
  66. TQuickFileMonitor = TFileMonitor;
  67. implementation
  68. constructor TFileMonitor.Create;
  69. begin
  70. inherited Create(True);
  71. Self.FreeOnTerminate := False;
  72. fInterval := 1000;
  73. fExists := False;
  74. fModifedDate := 0;
  75. fCurrentMonitorNotify := mnNone;
  76. fNotifies := [mnFileCreated,mnFileModified,mnFileDeleted];
  77. {$IFDEF FPC}
  78. fTickEvent := TSimpleEvent.Create;
  79. {$ELSE}
  80. fTickEvent := TSimpleEvent.Create(nil,True,False,'');
  81. {$ENDIF}
  82. end;
  83. destructor TFileMonitor.Destroy;
  84. begin
  85. if not Terminated then Terminate;
  86. Self.WaitFor;
  87. fTickEvent.SetEvent;
  88. fTickEvent.Free;
  89. inherited;
  90. end;
  91. procedure TFileMonitor.Execute;
  92. var
  93. LastModifiedDate : TDateTime;
  94. begin
  95. inherited;
  96. while not Terminated do
  97. begin
  98. fCurrentMonitorNotify := mnNone;
  99. if fTickEvent.WaitFor(fInterval) = TWaitResult.wrTimeout then
  100. begin
  101. if fEnabled then
  102. begin
  103. if TFile.Exists(fFileName) then
  104. begin
  105. if fExists then
  106. begin
  107. if mnFileModified in fNotifies then
  108. begin
  109. LastModifiedDate := TFile.GetLastWriteTime(fFileName);
  110. if LastModifiedDate > fModifedDate then
  111. begin
  112. fCurrentMonitorNotify := mnFileModified;
  113. fModifedDate := LastModifiedDate;
  114. end;
  115. end;
  116. end
  117. else
  118. begin
  119. if mnFileCreated in fNotifies then fCurrentMonitorNotify := mnFileCreated;
  120. LastModifiedDate := TFile.GetLastWriteTime(fFileName);
  121. fModifedDate := LastModifiedDate;
  122. end;
  123. fExists := True;
  124. end
  125. else
  126. begin
  127. //check if file deleted
  128. if mnFileDeleted in fNotifies then
  129. begin
  130. if fExists then
  131. begin
  132. fExists := False;
  133. fCurrentMonitorNotify := mnFileDeleted;
  134. end;
  135. end;
  136. end;
  137. if fCurrentMonitorNotify <> mnNone then
  138. begin
  139. if IsConsole then NotifyEvent
  140. else Synchronize(NotifyEvent);
  141. end;
  142. end;
  143. end;
  144. end;
  145. end;
  146. procedure TFileMonitor.SetEnabled(Status : Boolean);
  147. begin
  148. if (Status) and {$IFNDEF FPC}(not Started){$ELSE}(Suspended){$ENDIF} then Start;
  149. if fEnabled <> Status then
  150. begin
  151. fEnabled := Status;
  152. //gets current values
  153. if TFile.Exists(fFileName) then
  154. begin
  155. fExists := True;
  156. fModifedDate := TFile.GetLastWriteTime(fFileName);
  157. end;
  158. end;
  159. end;
  160. procedure TFileMonitor.NotifyEvent;
  161. begin
  162. if Assigned(fOnChangeNotify) then fOnChangeNotify(fCurrentMonitorNotify);
  163. end;
  164. end.