?
Solved

Detect File Changes in Dir

Posted on 2000-05-02
6
Medium Priority
?
186 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
Technology Partners: 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 200 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

Technology Partners: 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!

Question has a verified solution.

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

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses

801 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