Solved

Checking the activity of a specific folder

Posted on 2003-11-08
15
318 Views
Last Modified: 2010-04-05
Hi, i was wondering if it is possilbe..  i want to check if a specific folder is updated.. such as new file has been move,deleted,copied,append. and then if this operation occurs. i want to backup the data in that folder into another. is it possible?
0
Comment
Question by:orafans
  • 6
  • 4
  • 4
  • +1
15 Comments
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
yes, it is possible
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
0
 
LVL 2

Expert Comment

by:monir
Comment Utility
The way described in the sample above is complicated and not working on Win9x it needs NT 2000 or XP

There is another way, very simple way and work on all Windows versions, it is by using the following three API functions:
 FindFirstChangeNotification
FindNextChangeNotification
FindCloseChangeNotification

If you want I will give you a tiny sample of code of how to use these functions.

Monir.
0
 

Author Comment

by:orafans
Comment Utility
Yes, i need an example on this one.. kretzschmar, your suggestion was great but the problem is that it returns an error stating that the parameter is not correct...
0
 

Author Comment

by:orafans
Comment Utility
Monir, can you please give me an example?
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
0
 
LVL 2

Expert Comment

by:monir
Comment Utility
Ok, the following is a component for File changing Notifications, save it as FileNotify.pas then run Delphi and instali it using (Component-> Install Component)  Menu.

I hope that helps you & sorry for the delay in my answer..

Monir.


{ Copyright (C) 1998-2000, written by Shkolnik Mike
  FIDOnet: 2:463/106.14
  E-Mail:  mshkolnik@scalabium.com
           mshkolnik@yahoo.com
  WEB: http://www.scalabium.com
       http://www.geocities.com/mshkolnik
  tel: 380-/44/-552-10-29
}
unit FileNotify;

interface

uses
  Windows, SysUtils, Classes;

type
  EFileNotificationError = class(Exception);

  TFileNotificationOption = (foFile, foFolder, foAttributes, foSize, foTime, foWatchSubFolders);
  TFileNotificationOptions = set of TFileNotificationOption;

  TFileNotifyEvent = procedure(Sender :TObject; Action: TFileNotificationOption) of object;

  TSMFileNotificator = class;

  TNotificationThread = class(TThread)
  private
    FOwner: TSMFileNotificator;
    FHandles: array[0..7] of THandle;
    FHandleFilters: array[0..7] of TFileNotificationOption;
    FHandleCount: Integer;
    FActiveFilter: TFileNotificationOption;

    procedure ReleaseHandles;
    procedure AllocateHandles;
  protected
    procedure Execute; override;
    procedure Notify;
  public
    constructor Create(Owner: TSMFileNotificator);
    destructor Destroy; override;
    procedure Reset;
  end;

  TSMFileNotificator = class(TComponent)
  private
    FThread: TNotificationThread;
    FFolder: string;
    FOptions: TFileNotificationOptions;
    FOnFileNotification: TFileNotifyEvent;

    procedure SetOptions(Value: TFileNotificationOptions);
    procedure SetFolder(Value: string);
  protected
    procedure Notify(Action: TFileNotificationOption); virtual;
    procedure Loaded; override;
  public
    constructor Create(AOwner: TCOmponent); override;
    destructor Destroy; override;
  published
    property Folder: string read FFolder write SetFolder;
    property Options: TFileNotificationOptions read FOptions write SetOptions;
    property OnFileNotification: TFileNotifyEvent read FOnFileNotification write FOnFileNotification;
  end;


procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('SMComponents', [TSMFileNotificator]);
end;


const
  SErrInstall = 'Could not install notification callback';
  SErrAllocHandle = 'Could not allocate notification object';


{ TNotificationThread }
const
  HANDLE_FILE = 0;
  HANDLE_DIR  = 1;
  HANDLE_ATTR = 2;
  HANDLE_SIZE = 3;
  HANDLE_TIME = 4;

constructor TNotificationThread.Create(Owner: TSMFileNotificator);
begin
  inherited Create(True);

  FOwner := Owner;
  FreeOnTerminate := False;
  Reset;
  Resume;
end;

destructor TNotificationThread.Destroy;
begin
  ReleaseHandles;

  inherited Destroy;
end;

procedure TNotificationThread.AllocateHandles;

  procedure SetNotification(FileNotificationOption: TFileNotificationOption);
  const
    ANotifyFilter: array[foFile..foTime] of Integer =
      (FILE_NOTIFY_CHANGE_FILE_NAME,
       FILE_NOTIFY_CHANGE_DIR_NAME,
       FILE_NOTIFY_CHANGE_ATTRIBUTES,
       FILE_NOTIFY_CHANGE_SIZE,
       FILE_NOTIFY_CHANGE_LAST_WRITE);
  begin
    FHandleFilters[FHandleCount] := FileNotificationOption;
    FHandles[FHandleCount] := FindFirstChangeNotification(PChar(FOwner.Folder), (foWatchSubFolders in FOwner.FOptions), ANotifyFilter[FileNotificationOption]);
    Inc(FHandleCount);
    if FHandles[FHandleCount-1] = INVALID_HANDLE_VALUE then
      raise EFileNotificationError.Create(SErrAllocHandle);
  end;

begin
  if (FOwner <> nil) and (FOwner.FOptions <> []) then
    try
      FillChar(FHandles, SizeOf(FHandles), 0);
      FHandleCount := 0;
      if (foFile in FOwner.FOptions) then
        SetNotification(foFile);
      if (foFolder in FOwner.FOptions) then
        SetNotification(foFolder);
      if (foAttributes in FOwner.FOptions) then
        SetNotification(foAttributes);
      if (foSize in FOwner.FOptions) then
        SetNotification(foSize);
      if (foTime in FOwner.FOptions) then
        SetNotification(foTime);
    except
      ReleaseHandles;
      raise;
    end;
end;

procedure TNotificationThread.ReleaseHandles;
var i: Integer;
begin
  for i := 0 to FHandleCount-1 do
    if FHandles[i] <> 0 then
      FindCloseChangeNotification(FHandles[i]);
  FillChar(FHandles, SizeOf(FHandles), 0);
  FillChar(FHandleFilters, Sizeof(FHandleFilters), 0);
  FHandleCount := 0;
end;

procedure TNotificationThread.Reset;
begin
  ReleaseHandles;
  AllocateHandles;
end;

procedure TNotificationThread.Execute;
var i, j: Integer;
begin
  while not Terminated do
    if FHandleCount > 0 then
    begin
      j := WaitForMultipleObjects(FHandleCount, @FHandles, False, 200);
      for i := 0 to FHandleCount-1 do
        if j = (WAIT_OBJECT_0 + i) then
        begin
          FActiveFilter := FHandleFilters[i];
          Synchronize(Notify);
          FindNextChangeNotification(FHandles[i]);
          break;
        end;
    end
    else
      Sleep(0);
end;

procedure TNotificationThread.Notify;
begin
  FOwner.Notify(FActiveFilter);
end;


{ TSMFileNotificator }
constructor TSMFileNotificator.Create(AOwner: TCOmponent);
begin
  inherited Create(AOwner);

  FOptions := [foFile, foFolder];
end;

destructor TSMFileNotificator.Destroy;
begin
  if Assigned(FThread) then
  begin
    FThread.Free;
    FThread := nil;
  end;

  inherited Destroy;
end;

procedure TSMFileNotificator.Loaded;
begin
  inherited Loaded;

  if not (csDesigning in ComponentState) then
    FThread := TNotificationThread.Create(Self);
end;

procedure TSMFileNotificator.Notify(Action: TFileNotificationOption);
begin
  if Assigned(OnFileNotification) then
    OnFileNotification(Self, Action);
end;

procedure TSMFileNotificator.SetOptions(Value: TFileNotificationOptions);
begin
  if Value <> Options then
  begin
    FOptions := Value;
    if Assigned(FThread) then
      FThread.Reset;
  end;
end;

procedure TSMFileNotificator.SetFolder(Value: string);
begin
  if (Value <> FFolder) then
  begin
    FFolder := Value;
    if Assigned(FThread) then
      FThread.Reset;
  end;
end;

end.
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 33

Expert Comment

by:Slick812
Comment Utility
monir,
Is is OK to post Copyright  Code here at EE? ?
What country is it  Copyright in?
0
 
LVL 2

Expert Comment

by:monir
Comment Utility
It is free code, the only price is to state the owner of the code, so what is wrong with that?

Monir.
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
CopyRight is a LEGAL thing, like international laws, and means that you can NOT copy or use something that is CopyRighted without express Legal premission, do you know any thing about internaional copyright law?

you might  ask at the community support

http://www.experts-exchange.com/Community_Support/

and I'm not sure at a public forum like EE, you can have qualifiers like CopyRight or the only price is to state the owner of the code, I think in the EE sign up agreement they say something about the code here is for public access? ?

but I don't really care one way or the other. . . just trying to help you out
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
orafans, Sorry

I really apploigize about posting this here on your question, please continue with your coding questions or statements
0
 

Author Comment

by:orafans
Comment Utility
i was wondering if you could give a simple code or instruction that will do the said above question that i have posted earlier... thanks..
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
I do not think there is any "Simple" code to do what you want
What have you tried?
0
 

Author Comment

by:orafans
Comment Utility
Well, i am just new to delphi.. but i was wondering if there is a way.. can you help me please?
0
 
LVL 2

Accepted Solution

by:
monir earned 250 total points
Comment Utility
Well,
Here is the smallest code, I have took it from MSDN, it is with code in C:

Monir.



Obtaining Directory Change Notifications

An application can monitor the contents of a directory and its subdirectories by using change notifications. Waiting for a change notification is similar to having a read operation pending against a directory and, if necessary, its subdirectories. When something changes within the directory being watched, the read operation is completed. For example, an application can use these functions to update a directory listing whenever a file name within the monitored directory changes.


An application can specify a set of conditions that trigger a change notification by using the FindFirstChangeNotification function. The conditions include changes to file names, directory names, attributes, file size, time of last write, and security. This function also returns a handle that can be waited on by using the wait functions. If the wait condition is satisfied, FindNextChangeNotification can be used to provide a notification handle to wait on subsequent changes. The FindCloseChangeNotification function closes the notification handle.

Another way to monitor directory changes is by using the ReadDirectoryChangesW function. To track changes on a volume, see change journals.



The following example monitors the directory tree starting at C:\ for directory name changes. It also monitors the C:\Windows directory for file name changes. The example uses the FindFirstChangeNotification function to create two notification handles and the WaitForMultipleObjects function to wait on the handles. Whenever a directory is created or deleted in the tree starting at C:\ , the example updates the entire directory tree. Whenever a file is created or deleted in the C:\Windows directory, the example refreshes the directory.

DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
 
// Watch the C:\WINDOWS directory for file creation and
// deletion.
 
dwChangeHandles[0] = FindFirstChangeNotification(
    "C:\\WINDOWS",                 // directory to watch
    FALSE,                         // do not watch the subtree
    FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
 
if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
    ExitProcess(GetLastError());
 
// Watch the C:\ subtree for directory creation and
// deletion.
 
dwChangeHandles[1] = FindFirstChangeNotification(
    "C:\\",                        // directory to watch
    TRUE,                          // watch the subtree
    FILE_NOTIFY_CHANGE_DIR_NAME);  // watch dir. name changes
 
if (dwChangeHandles[1] == INVALID_HANDLE_VALUE)
    ExitProcess(GetLastError());
 
// Change notification is set. Now wait on both notification
// handles and refresh accordingly.
 
while (TRUE)
{
 
    // Wait for notification.
 
    dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles,
        FALSE, INFINITE);
 
    switch (dwWaitStatus)
    {
        case WAIT_OBJECT_0:
 
        // A file was created or deleted in C:\WINDOWS.
        // Refresh this directory and restart the
        // change notification. RefreshDirectory is an
        // application-defined function.
 
            RefreshDirectory("C:\\WINDOWS")
            if ( FindNextChangeNotification(
                    dwChangeHandles[0]) == FALSE )
                ExitProcess(GetLastError());
            break;
 
        case WAIT_OBJECT_0 + 1:
 
        // A directory was created or deleted in C:\.
        // Refresh the directory tree and restart the
        // change notification. RefreshTree is an
        // application-defined function.
 
            RefreshTree("C:\\");
            if (FindNextChangeNotification(
                    dwChangeHandles[1]) == FALSE)
                ExitProcess(GetLastError());
            break;
 
        default:
            ExitProcess(GetLastError());
    }
}
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

772 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now