Quick.FileMonitor.pas 4.7 KB

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