Solved

Detect File Changes in Dir

Posted on 2000-05-02
6
185 Views
Last Modified: 2012-05-04
How can i detect if a File have changed in a special directory (I mean a new File, a File was deleted . . . .)
And how can i detect if a SubFolder was changed ?
0
Comment
Question by:snoopy_Spy
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
6 Comments
 
LVL 7

Expert Comment

by:daniel_c
ID: 2771592
You can use TTimer to detect it.
I give you an example:
1. Make New Application from Delphi IDE.
2. Add component TFileListBox
3. Add Component TTimer

On Form Event Create, put this code:
procedure TForm1.FormCreate(Sender: TObject);
begin
  FileListBox1.Directory:= 'C:\';
end;

On TTimer Event Timer, put this code:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  FileListBox1.Update;
end;


Below is the whole code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, FileCtrl, ExtCtrls;

type
  TForm1 = class(TForm)
    FileListBox1: TFileListBox;
    Timer1: TTimer;
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose:= false;
  ShowMessage('Sorry, cannot close!');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FileListBox1.Directory:= 'C:\';
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  FileListBox1.Update;
end;

end.

It will always update information on folder C:\.

Hope it will help!

Regards,

Daniel
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2772374
Under win9x you can use FindFirstFileNotification, but this API only tells you that *something* has happened, it doesn't tell you the filename etc.
Under winNT you can use ReadDirectoryChangesW, which tells you all you want to know.

Regards, Madshi.
0
 
LVL 1

Expert Comment

by:Asw
ID: 2773113
Listening.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:snoopy_Spy
ID: 2773152
Sorry but this is not the way i would like to make it !

Madshi
Have you some further infos about the two functions ?
0
 
LVL 20

Accepted Solution

by:
Madshi earned 50 total points
ID: 2773182
Hmmm... There's a component in the free RxLibrary for FindFirstFileNotification. Look here:

http://www.rxlib.com/

I've nothing for ReadDirectoryChangesW, sorry.

Regards, Madshi.
0
 
LVL 2

Expert Comment

by:mullet_attack
ID: 2773211
here's a component I wrote some years ago, so I can't remember a lot about it, but it provides a changed event if the montitored directory changes. I can also monitor subdirectories, and allows you to specify what you'd like to monitor.

Anyway, have a look at it and see if it's what you want.

unit changed;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  EChangeError = class(exception);

  TChangeSet = (ntFileName, ntDirName, ntAttributes, ntSize, ntLastWrite, ntSecurity);
  TChangeType = set of TChangeSet;

  TChanged = class;

  TWaitThread = class(TThread)
  private
    EventArray:array[0..1] of THandle;
    fNotifyType : DWORD;
    fChanged : TChanged;
  protected
    Procedure Execute;override;
  public
    Constructor Create(NotifyType:DWORD;Changed:TChanged);
  end;

  TChanged = class(TComponent)
  private
    fEnabled : boolean;
    fSubDirs : boolean;
    fPath : string;
    fChangeType : TChangeType;
    fLocalChangeType : DWORD;
    fWaitThread : TWaitThread;
    szPath : array[0..255] of char;
    fOnChanged : TNotifyEvent;
    procedure UpdateThread;
  protected
    procedure SetEnabled(value:boolean);
    procedure SetSubDirs(value:boolean);
    procedure SetPath(value:string);
    procedure SetChangeType(value:TChangeType);
    procedure DoChanged;
  public
    Constructor Create(AOwner:TComponent);override;
    Destructor Destroy;override;
  published
    Property Enabled:boolean read fEnabled write SetEnabled;
    Property SubDirs:boolean read fSubDirs write SetSubDirs;
    Property OnChanged:TNotifyEvent read fOnChanged write fOnChanged;
    Property ChangeType:TChangeType read fChangeType write SetChangeType;
    Property Path:string read fPath write SetPath;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Planetech', [TChanged]);
end;

Constructor TWaitThread.Create(NotifyType:DWORD;Changed:TChanged);
begin
  inherited Create(False);
  fNotifyType := NotifyType;
  fChanged := Changed;
end;

procedure TWaitThread.Execute;
begin
  while not Terminated do with (fChanged as TChanged) do
    begin
      EventArray[0] := CreateEvent(Nil,    // no security attributes
                                   TRUE,    // manual reset event
                                   FALSE,   // not-signalled
                                   Nil);   // no name
      EventArray[1] := FindFirstChangeNotification(szPath,
                                                   fSubDirs,
                                                   fNotifyType);
      WaitForMultipleObjects(2, @EventArray, FALSE, INFINITE);
      synchronize(doChanged);

      FindCloseChangeNotification(EventArray[1]);
      CloseHandle(EventArray[0]);
    end;
end;
//----------------------------------------------------------------------------

Constructor TChanged.Create(AOwner:TComponent);
var
  t:integer;
begin
  inherited Create(AOwner);
end;

Destructor TChanged.Destroy;
begin
  inherited Destroy;
end;

procedure TChanged.SetEnabled(value:boolean);
begin
  if value = fEnabled then exit;
  fEnabled := value;
  UpdateThread;
end;

procedure TChanged.SetSubDirs(value:boolean);
begin
  if value = fSubDirs then exit;
  fSubDirs := value;
  UpdateThread;
end;

procedure TChanged.SetPath(value:string);
begin
  if value = fPath then exit;
  fPath := value;
  StrPCopy(szPath, fPath);
  UpdateThread;
end;

procedure TChanged.SetChangeType(value:TChangeType);
begin
  if fChangeType = value then exit;
  fLocalChangeType := 0;
  if ntFileName in value then fLocalChangeType := fLocalChangeType or FILE_NOTIFY_CHANGE_FILE_NAME;
  if ntDirName in value then fLocalChangeType := fLocalChangeType or FILE_NOTIFY_CHANGE_DIR_NAME;
  if ntAttributes in value then fLocalChangeType := fLocalChangeType or FILE_NOTIFY_CHANGE_ATTRIBUTES;
  if ntSize in value then fLocalChangeType := fLocalChangeType or FILE_NOTIFY_CHANGE_SIZE;
  if ntLastWrite in value then fLocalChangeType := fLocalChangeType or FILE_NOTIFY_CHANGE_LAST_WRITE;
  if ntSecurity in value then fLocalChangeType := fLocalChangeType or FILE_NOTIFY_CHANGE_SECURITY;
  fChangeType := value;
end;

procedure TChanged.UpdateThread;
begin
  if (not (csDesigning in ComponentState) and (fPath = '')) then
      Raise EChangeError.create('Path cannot be Null');
  if (not (csDesigning in ComponentState) and (fLocalChangeType = 0)) then
      Raise EChangeError.create('Must Specify ChangeType');
  if fWaitThread <> nil then
     begin
       fWaitThread.Terminate;
       PulseEvent(fWaitThread.EventArray[0]);
       WaitForSingleObject(fWaitThread.handle, INFINITE);
       CloseHandle(fWaitThread.handle);
       fWaitThread := nil;
     end;
  if fEnabled then
    fWaitThread := TWaitThread.create(fLocalChangeType,self);
end;

procedure TChanged.DoChanged;
begin
  if assigned (fOnChanged) then fOnChanged(Self);
end;

end.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

724 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question