Quick.FileMonitor.pas 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. { ***************************************************************************
  2. Copyright (c) 2015-2021 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 : 10/05/2021
  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. fIsThreadStarted : Boolean;
  54. procedure SetEnabled(Status : Boolean);
  55. procedure NotifyEvent;
  56. protected
  57. procedure Execute; override;
  58. public
  59. constructor Create;
  60. destructor Destroy; override;
  61. property FileName : string read fFileName write fFileName;
  62. property Interval : Integer read fInterval write fInterval;
  63. property Notifies : TMonitorWatch read fNotifies write fNotifies;
  64. property OnFileChange : TFileChangeNotify read fOnChangeNotify write fOnChangeNotify;
  65. property Enabled : Boolean read fEnabled write SetEnabled;
  66. end;
  67. TQuickFileMonitor = TFileMonitor;
  68. implementation
  69. constructor TFileMonitor.Create;
  70. begin
  71. inherited Create(True);
  72. fIsThreadStarted := False;
  73. fEnabled := False;
  74. Self.FreeOnTerminate := False;
  75. fInterval := 1000;
  76. fExists := False;
  77. fModifedDate := 0;
  78. fCurrentMonitorNotify := mnNone;
  79. fNotifies := [mnFileCreated,mnFileModified,mnFileDeleted];
  80. {$IFDEF FPC}
  81. fTickEvent := TSimpleEvent.Create;
  82. {$ELSE}
  83. fTickEvent := TSimpleEvent.Create(nil,True,False,'');
  84. {$ENDIF}
  85. end;
  86. destructor TFileMonitor.Destroy;
  87. begin
  88. if not Terminated then Terminate;
  89. Self.WaitFor;
  90. fTickEvent.SetEvent;
  91. fTickEvent.Free;
  92. inherited;
  93. end;
  94. procedure TFileMonitor.Execute;
  95. var
  96. LastModifiedDate : TDateTime;
  97. begin
  98. inherited;
  99. while not Terminated do
  100. begin
  101. fCurrentMonitorNotify := mnNone;
  102. if fTickEvent.WaitFor(fInterval) = TWaitResult.wrTimeout then
  103. begin
  104. if fEnabled then
  105. begin
  106. if TFile.Exists(fFileName) then
  107. begin
  108. if fExists then
  109. begin
  110. if mnFileModified in fNotifies then
  111. begin
  112. LastModifiedDate := TFile.GetLastWriteTime(fFileName);
  113. if LastModifiedDate > fModifedDate then
  114. begin
  115. fCurrentMonitorNotify := mnFileModified;
  116. fModifedDate := LastModifiedDate;
  117. end;
  118. end;
  119. end
  120. else
  121. begin
  122. if mnFileCreated in fNotifies then fCurrentMonitorNotify := mnFileCreated;
  123. LastModifiedDate := TFile.GetLastWriteTime(fFileName);
  124. fModifedDate := LastModifiedDate;
  125. end;
  126. fExists := True;
  127. end
  128. else
  129. begin
  130. //check if file deleted
  131. if mnFileDeleted in fNotifies then
  132. begin
  133. if fExists then
  134. begin
  135. fExists := False;
  136. fCurrentMonitorNotify := mnFileDeleted;
  137. end;
  138. end;
  139. end;
  140. if fCurrentMonitorNotify <> mnNone then
  141. begin
  142. if IsConsole then NotifyEvent
  143. else Synchronize(NotifyEvent);
  144. end;
  145. end;
  146. end;
  147. end;
  148. end;
  149. procedure TFileMonitor.SetEnabled(Status : Boolean);
  150. begin
  151. if fEnabled <> Status then
  152. begin
  153. if Status then
  154. begin
  155. //gets current values
  156. if TFile.Exists(fFileName) then
  157. begin
  158. fExists := True;
  159. fModifedDate := TFile.GetLastWriteTime(fFileName);
  160. end;
  161. end;
  162. if not fIsThreadStarted then
  163. begin
  164. fIsThreadStarted := True;
  165. if (Status) and {$IFNDEF FPC}(Started = False){$ELSE}(Suspended){$ENDIF} then Start;
  166. end;
  167. fEnabled := Status;
  168. end;
  169. end;
  170. procedure TFileMonitor.NotifyEvent;
  171. begin
  172. if Assigned(fOnChangeNotify) then fOnChangeNotify(fCurrentMonitorNotify);
  173. end;
  174. end.