Jump to content
pyscripter

New file system monitoring component

Recommended Posts

Whilst there are many Delphi components for detecting changes to file system folders they suffer from serious limitations:

  • typically they only allow you to monitor a single folder
  • they do not support the monitoring of specific files
  • they rely on the FindFirstChangeNotification API which gives no information about what has changed, requiring an inefficient search.

 

I have created a new file system monitoring library that addresses the above limitations.

 

Features:

  • Easy to use, but also suitable for heavy duty monitoring
  • Single unit with no external dependencies
  • Allows monitoring folders and/or specific files
  • Uses the ReadDirectoryChangesW API which provides information about what exactly was changed
  • A single instance of the component can handle the monitoring of many folders and/or files
  • Uses an I/O completion port for efficient handling of large numbers of requests
  • A single thread handles all requests
  • A different notification handler can be specified for each request
  • You can have multiple handlers for each folder or file

  • When you monitor folders you can specify whether you want to also monitor subfolders

 

Installation:

You do not need to install the library. Just download or clone the repo and add the source subdirectory to the Library path.

 

Usage:

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Create the IFileSystemMonitor interface
  FFileSystemMonitor := CreateFileSystemMonitor;
  // Monitor a directory
  FFileSystemMonitor.AddDirectory(TPath.GetTempPath, False, HandleChange);
  // Also monitor a specific file
  FFileSystemMonitor.AddFile('pathtoyourfile',  HandleChange);
end;

procedure TForm1.HandleChange(Sender: TObject; const Path: string;
  ChangeType: TFileChangeType);
begin
  with lvEventList.Items.Add do
  begin
    Caption := GetEnumName(TypeInfo(TFileChangeType), Integer(ChangeType));
    SubItems.Add(Path);
  end;
end;

To stop monitoring a specific file or folder you use the following methods:

    function RemoveDirectory(const Directory: string; OnChange: TMonitorChangeHandler): Boolean;
    function RemoveFile(const FilePath: string; OnChange: TMonitorChangeHandler): Boolean;

 

Edited by pyscripter
  • Like 17
  • Thanks 11

Share this post


Link to post

Very nice.  Way better than constant polling for sure.

I think I have no use for this now, but have to think about it, maybe I can think of something.

In previous live used FindFirstChangeNotification  API, did not knoew that there is other API for this.

-Tee-

Edited by Tommi Prami
typo

Share this post


Link to post

Sorry for asking, but is polling still necessary if the monitoring application (which uses IFileSystemMonitor) was not running for a while, and during that time changes happened?

Or does IFileSystemMonitor provide ways to detect changes which happened while it was "absent"?

Share this post


Link to post

Hi,

 

It looks simple and good.

Does it work across network or VPN ?

i.e. can a server directory be monitored from an app running your monitoring class on a client PC, connected to the server through network ?

 

Mel

 

Share this post


Link to post
38 minutes ago, M.e.l said:

Does it work across network or VPN ?

i.e. can a server directory be monitored from an app running your monitoring class on a client PC, connected to the server through network ?

VPN is just transport layer encryption and is not relevant.

 

The documentation for ReadDirectoryChangesW answers your other question:

Quote

If the network redirector or the target file system does not support this operation, the function fails with ERROR_INVALID_FUNCTION.

Quote

In Windows 8 and Windows Server 2012, this function is supported by the following technologies.

Technology Supported
Server Message Block (SMB) 3.0 protocol Yes
SMB 3.0 Transparent Failover (TFO) Yes
SMB 3.0 with Scale-out File Shares (SO) Yes
Cluster Shared Volume File System (CsvFS) Yes
Resilient File System (ReFS) Yes

 

 

Share this post


Link to post

@mjustin

Have a look at the source code.  https://github.com/pyscripter/FileSystemMonitor/blob/2dd27a0570ae2f839acb9de3bf67bb2247893784/Source/FileSystemMonitor.pas#L415C16-L415C41

All the thread does is wait on the I/O complection port using GetQueuedCompletionStatus.  This function blocks until a change happens. The only polling that takes place is to check every 5 seconds, for deletion/rename of the monitored directories themselves, which are not reported by ReadDirectoryChanges.  Folders can be attached to/detached from the completion port at any time, without any problem.

Share this post


Link to post
41 minutes ago, pyscripter said:

deletion/rename of the monitored directories themselves, which are not reported by ReadDirectoryChanges.

...unless you also monitor the parent directory. Maybe make the polling optional?

  • Like 1

Share this post


Link to post
1 hour ago, Anders Melander said:

...unless you also monitor the parent directory.

You will still have the same issue if the parent directory (or the parent of the parent...) gets deleted or renamed.  Even if it is not,  you may be getting many more notifications than you need.  Also you would have to watch subfolders, which you may not want. 

 

It is not worth it. Checking every x seconds whether the monitored directories still exist is a tiny overhead.

Edited by pyscripter

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×