Recent

Author Topic: [SOLVED] Watching a folder for changes with DirWatch  (Read 507 times)

fatmonk

  • Full Member
  • ***
  • Posts: 193
[SOLVED] Watching a folder for changes with DirWatch
« on: July 31, 2019, 03:08:10 pm »
I'm trying to use DirWatch (http://www.angusj.com/delphi/dirwatch.html) to monitor a directory for changes but am running into problems getting the module to compile under Lazarus v1.8.2.

The first issues I'm having don't seem to be a compatibility issue, rather they look like an issue with the code itself.

Line 48 of the source declares a procedure WndProc as:

   
Code: Pascal  [Select]
  1. procedure WndProc(var aMsg: TMessage);

but line 125 then tries to use this procedure with no arguments as follows:

   
Code: Pascal  [Select]
  1. fWindowHandle := AllocateHWnd(WndProc);

I've tried to get my head around the source, but I'm afraid it's way beyond me (other than understanding that it seems to do what I want via the Windows API rather than just periodically checking the contents of a folder).

Is there an updated version of this module or does anyone know how I can get this running?

Thanks,

FM
« Last Edit: July 31, 2019, 06:31:04 pm by fatmonk »

lucamar

  • Hero Member
  • *****
  • Posts: 1982
Re: Watching a folder for changes with DirWatch
« Reply #1 on: July 31, 2019, 04:31:25 pm »
but line 125 then tries to use this procedure with no arguments as follows:
Code: Pascal  [Select]
  1. fWindowHandle := AllocateHWnd(WndProc);

IIRC, the "WndProc" in AlocateHWnd() is a procedural parameter i.e. that line is passing the address of WndProc to AllocateHWnd. If the code is in Delphi mode (which it must be if it's not giving you compie-time errors) it's OK.

The equivalent in ObjFpc mode would be:
Code: Pascal  [Select]
  1. fWindowHandle := AllocateHWnd(@WndProc);

Quote from: fatmonk
Is there an updated version of this module or does anyone know how I can get this running?

What problems are you having? Try to be as precise as you can.
« Last Edit: July 31, 2019, 04:34:14 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

ASerge

  • Hero Member
  • *****
  • Posts: 1386
Re: Watching a folder for changes with DirWatch
« Reply #2 on: July 31, 2019, 05:30:16 pm »
I'm trying to use DirWatch (http://www.angusj.com/delphi/dirwatch.html) to monitor a directory for changes but am running into problems getting the module to compile under Lazarus v1.8.2.
Active Lazarus release 2.0.2.
By the specified link the component looks unreliable. It read/change fields in thread without synchronizing the access.
Maybe you should use what is already in Lazarus, without the need for threads?
Example:
Code: Pascal  [Select]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, StdCtrls, InterfaceBase;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     btnStartWait: TButton;
  13.     btnStopWait: TButton;
  14.     Memo1: TMemo;
  15.     procedure btnStartWaitClick(Sender: TObject);
  16.     procedure btnStopWaitClick(Sender: TObject);
  17.     procedure FormDestroy(Sender: TObject);
  18.   private
  19.     FEvent: PEventHandler;
  20.     procedure DirChanged(AData: PtrInt; AFlags: DWORD);
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. uses Windows;
  29.  
  30. {$R *.lfm}
  31.  
  32. procedure TForm1.btnStartWaitClick(Sender: TObject);
  33. var
  34.   H: THandle;
  35. begin
  36.   H := FindFirstChangeNotificationW('c:\Temp', True, FILE_NOTIFY_CHANGE_FILE_NAME);
  37.   if H = INVALID_HANDLE_VALUE then
  38.     Exit;
  39.   FEvent := WidgetSet.AddEventHandler(H, 0, @DirChanged, H);
  40. end;
  41.  
  42. procedure TForm1.btnStopWaitClick(Sender: TObject);
  43. begin
  44.   WidgetSet.RemoveEventHandler(FEvent);
  45. end;
  46.  
  47. procedure TForm1.DirChanged(AData: PtrInt; AFlags: DWORD);
  48. begin
  49.   Memo1.Append(TimeToStr(Time));
  50.   if not FindNextChangeNotification(AData) then
  51.     WidgetSet.RemoveEventHandler(FEvent);
  52. end;
  53.  
  54. procedure TForm1.FormDestroy(Sender: TObject);
  55. begin
  56.   WidgetSet.RemoveEventHandler(FEvent);
  57. end;
  58.  
  59. end.

fatmonk

  • Full Member
  • ***
  • Posts: 193
Re: Watching a folder for changes with DirWatch
« Reply #3 on: July 31, 2019, 06:30:04 pm »
@ASerge I had no idea that it was built into Lazarus!

I searched and searched online a couple of years ago and found various ways to do this, but back then I didn't find any mention of it.

Your clues here should really help me out.

Big thanks,

FM

ASerge

  • Hero Member
  • *****
  • Posts: 1386
Re: Watching a folder for changes with DirWatch
« Reply #4 on: July 31, 2019, 08:36:00 pm »
Big thanks,

In my example I forgot FindCloseChangeNotification. More correct version
Code: Pascal  [Select]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, StdCtrls, InterfaceBase;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     btnStartWait: TButton;
  13.     btnStopWait: TButton;
  14.     Memo1: TMemo;
  15.     procedure btnStartWaitClick(Sender: TObject);
  16.     procedure btnStopWaitClick(Sender: TObject);
  17.     procedure FormDestroy(Sender: TObject);
  18.   private
  19.     FEventHandler: PEventHandler;
  20.     FWaitHandle: THandle;
  21.     procedure ClearEventHandler;
  22.     procedure DirChanged(AData: PtrInt; AFlags: DWORD);
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. uses Windows;
  31.  
  32. {$R *.lfm}
  33.  
  34. procedure TForm1.btnStartWaitClick(Sender: TObject);
  35. begin
  36.   if not Assigned(FEventHandler) then
  37.   begin
  38.     FWaitHandle := FindFirstChangeNotificationW('c:\Temp', True, FILE_NOTIFY_CHANGE_FILE_NAME);
  39.     if FWaitHandle <> INVALID_HANDLE_VALUE then
  40.       FEventHandler := WidgetSet.AddEventHandler(FWaitHandle, 0, @DirChanged, 0);
  41.   end;
  42. end;
  43.  
  44. procedure TForm1.ClearEventHandler;
  45. begin
  46.   if Assigned(FEventHandler) then
  47.   begin
  48.     FindCloseChangeNotification(FWaitHandle);
  49.     WidgetSet.RemoveEventHandler(FEventHandler);
  50.   end;
  51. end;
  52.  
  53. procedure TForm1.btnStopWaitClick(Sender: TObject);
  54. begin
  55.   ClearEventHandler;
  56. end;
  57.  
  58. procedure TForm1.DirChanged(AData: PtrInt; AFlags: DWORD);
  59. begin
  60.   Memo1.Append(TimeToStr(Time));
  61.   if not FindNextChangeNotification(FWaitHandle) then
  62.     ClearEventHandler;
  63. end;
  64.  
  65. procedure TForm1.FormDestroy(Sender: TObject);
  66. begin
  67.   ClearEventHandler;
  68. end;
  69.  
  70. end.

sstvmaster

  • Full Member
  • ***
  • Posts: 112
Re: [SOLVED] Watching a folder for changes with DirWatch
« Reply #5 on: July 31, 2019, 11:37:10 pm »
Or you also can use this package from JUAN CARLOS, called DirMonitor. It can be found in tab "JC Components". see attachment.
Lazarus 2.0.4 x32
Lazarus 2.1.0 Trunk x32
OS Win 7 32bit

fatmonk

  • Full Member
  • ***
  • Posts: 193
Re: [SOLVED] Watching a folder for changes with DirWatch
« Reply #6 on: August 01, 2019, 02:36:36 pm »
@ASerge Does this provide the name of the added/changed file anywhere?

I've hunted around the docs but haven'd found anything other than a notification that a change has happened.

Thanks,

FM

ASerge

  • Hero Member
  • *****
  • Posts: 1386
Re: [SOLVED] Watching a folder for changes with DirWatch
« Reply #7 on: August 01, 2019, 03:36:34 pm »
@ASerge Does this provide the name of the added/changed file anywhere?
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstchangenotificationw:
FILE_NOTIFY_CHANGE_FILE_NAME - Any file name change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file name.

fatmonk

  • Full Member
  • ***
  • Posts: 193
Re: [SOLVED] Watching a folder for changes with DirWatch
« Reply #8 on: August 01, 2019, 03:40:39 pm »
@sstvmaster Thanks for this... that component takes a bunch of the manual work out of it!

And the name of the file added/changed etc is right there in the Change Event (It took me a while to spot it, rather embarrassingly!)

Thanks,

FM
« Last Edit: August 01, 2019, 04:23:46 pm by fatmonk »

fatmonk

  • Full Member
  • ***
  • Posts: 193
Re: [SOLVED] Watching a folder for changes with DirWatch
« Reply #9 on: August 01, 2019, 03:46:16 pm »
@ASerge Does this provide the name of the added/changed file anywhere?
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstchangenotificationw:
FILE_NOTIFY_CHANGE_FILE_NAME - Any file name change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file name.

I can see that that sets the watcher to look for changes to the file name including adding or deleting a file, but reading and re-reading the docs I still can't find where I access the string that contains the name of the file that changed.

Apologies if I'm just being really stupid here. I'm obviously looking in all the wrong places!

Thanks,

FM

fred

  • Full Member
  • ***
  • Posts: 149
Re: [SOLVED] Watching a folder for changes with DirWatch
« Reply #10 on: August 01, 2019, 04:33:44 pm »
Perhaps looking in the right place but not reading? :)
Quote
This function does not indicate the change that satisfied the wait condition. To retrieve information about the specific change as part of the notification, use the
ReadDirectoryChangesW function.
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstchangenotificationw
Started with OmegaSoft Pascal on OS-9/68k , now Lazarus 2.0.2 / FPC 3.0.4 on Windows 7