123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- { ***************************************************************************
- Copyright (c) 2015-2021 Kike Pérez
- Unit : Quick.FileMonitor
- Description : Watch for single file changes
- Author : Kike Pérez
- Version : 1.2
- Created : 11/09/2017
- Modified : 10/05/2021
- This file is part of QuickLib: https://github.com/exilon/QuickLib
- ***************************************************************************
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- *************************************************************************** }
- unit Quick.FileMonitor;
- interface
- {$i QuickLib.inc}
- uses
- Classes,
- {$IFDEF MSWINDOWS}
- Windows,
- SyncObjs,
- {$ELSE}
- SyncObjs,
- {$ENDIF}
- SysUtils,
- {$IFDEF FPC}
- Quick.Files;
- {$ELSE}
- System.IOUtils;
- {$ENDIF}
- type
- TMonitorNotify = (mnNone, mnFileCreated, mnFileModified, mnFileDeleted);
- TMonitorWatch = set of TMonitorNotify;
- TFileChangeNotify = procedure(MonitorNofify : TMonitorNotify) of object;
- TFileMonitor = class(TThread)
- private
- fFileName : string;
- fTickEvent : TSimpleEvent;
- fInterval : Integer;
- fNotifies : TMonitorWatch;
- fEnabled : Boolean;
- fExists : Boolean;
- fModifedDate : TDateTime;
- fCurrentMonitorNotify : TMonitorNotify;
- fOnChangeNotify : TFileChangeNotify;
- fIsThreadStarted : Boolean;
- procedure SetEnabled(Status : Boolean);
- procedure NotifyEvent;
- protected
- procedure Execute; override;
- public
- constructor Create;
- destructor Destroy; override;
- property FileName : string read fFileName write fFileName;
- property Interval : Integer read fInterval write fInterval;
- property Notifies : TMonitorWatch read fNotifies write fNotifies;
- property OnFileChange : TFileChangeNotify read fOnChangeNotify write fOnChangeNotify;
- property Enabled : Boolean read fEnabled write SetEnabled;
- end;
- TQuickFileMonitor = TFileMonitor;
- implementation
- constructor TFileMonitor.Create;
- begin
- inherited Create(True);
- fIsThreadStarted := False;
- fEnabled := False;
- Self.FreeOnTerminate := False;
- fInterval := 1000;
- fExists := False;
- fModifedDate := 0;
- fCurrentMonitorNotify := mnNone;
- fNotifies := [mnFileCreated,mnFileModified,mnFileDeleted];
- {$IFDEF FPC}
- fTickEvent := TSimpleEvent.Create;
- {$ELSE}
- fTickEvent := TSimpleEvent.Create(nil,True,False,'');
- {$ENDIF}
- end;
- destructor TFileMonitor.Destroy;
- begin
- if not Terminated then Terminate;
- Self.WaitFor;
- fTickEvent.SetEvent;
- fTickEvent.Free;
- inherited;
- end;
- procedure TFileMonitor.Execute;
- var
- LastModifiedDate : TDateTime;
- begin
- inherited;
- while not Terminated do
- begin
- fCurrentMonitorNotify := mnNone;
- if fTickEvent.WaitFor(fInterval) = TWaitResult.wrTimeout then
- begin
- if fEnabled then
- begin
- if TFile.Exists(fFileName) then
- begin
- if fExists then
- begin
- if mnFileModified in fNotifies then
- begin
- LastModifiedDate := TFile.GetLastWriteTime(fFileName);
- if LastModifiedDate > fModifedDate then
- begin
- fCurrentMonitorNotify := mnFileModified;
- fModifedDate := LastModifiedDate;
- end;
- end;
- end
- else
- begin
- if mnFileCreated in fNotifies then fCurrentMonitorNotify := mnFileCreated;
- LastModifiedDate := TFile.GetLastWriteTime(fFileName);
- fModifedDate := LastModifiedDate;
- end;
- fExists := True;
- end
- else
- begin
- //check if file deleted
- if mnFileDeleted in fNotifies then
- begin
- if fExists then
- begin
- fExists := False;
- fCurrentMonitorNotify := mnFileDeleted;
- end;
- end;
- end;
- if fCurrentMonitorNotify <> mnNone then
- begin
- if IsConsole then NotifyEvent
- else Synchronize(NotifyEvent);
- end;
- end;
- end;
- end;
- end;
- procedure TFileMonitor.SetEnabled(Status : Boolean);
- begin
- if fEnabled <> Status then
- begin
- if Status then
- begin
- //gets current values
- if TFile.Exists(fFileName) then
- begin
- fExists := True;
- fModifedDate := TFile.GetLastWriteTime(fFileName);
- end;
- end;
- if not fIsThreadStarted then
- begin
- fIsThreadStarted := True;
- if (Status) and {$IFNDEF FPC}(Started = False){$ELSE}(Suspended){$ENDIF} then Start;
- end;
- fEnabled := Status;
- end;
- end;
- procedure TFileMonitor.NotifyEvent;
- begin
- if Assigned(fOnChangeNotify) then fOnChangeNotify(fCurrentMonitorNotify);
- end;
- end.
|