Solved

File Notification using ReadDirectoryChanges API

Posted on 1998-11-04
4
2,666 Views
Last Modified: 2012-06-27
I'm trying to get the ReadDirectoryChangesW call for Win NT to work (it is not supported for Win 95).  Below is the code.  Has anyone implemented it successufully in Delphi?  If so could you post the code?  In the code below, the call to GetQueuedCompletionStatus holds until a file change is made in the c:\temp2 directory.  That's cool, but I can't figure out how to decode the information returned.  The code is based on an example from MSDN.


interface

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

const
  FILE_LIST_DIRECTORY = $0001;
  MAX_PATH = 80;
  MAX_BUFFER = 4096;
type
  PDirectoryInfo = ^TDirectoryInfo;

  PBuffer = ^TBuffer;
  TBuffer = array [0..MAX_BUFFER - 1] of Char;

  TDirectoryInfo = record
    hDir: THandle;
    lpszDirName: array [0..MAX_PATH - 1] of WChar;
    lpBuffer: array [0..MAX_BUFFER - 1] of Char;
    dwBufLength: DWORD;
    Overlapped: POverlapped;
  end;

  PFileNotifyInformation = ^TFileNotifyInformation;
  TFileNotifyInformation = record
    NextEntryOffset: DWord;
    Action: DWord;
    FileNameLength: DWord;
    FileName: WideChar;
  end;

type
  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.DFM}

procedure TForm3.Button1Click(Sender: TObject);
var
  ChangeBuffer: PFileNotifyInformation;
  fni: PFileNotifyInformation;
  Info, NumBytes, Offset, LastError: DWord;
  DirHandle, CompletionPort: THandle;
  Overlapped: POverlapped;
  Queue, ReadResult: BOOL;
  BytesReturned: PDWord;
  PFileNotifyInfo: PFileNotifyInformation;
begin
  New(ChangeBuffer);

  New(Overlapped);

  DirHandle := CreateFile(PChar('c:\temp2')
                          , FILE_LIST_DIRECTORY
                          , (FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE)
                          , nil
                          , OPEN_EXISTING
                          , FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED
                          , 0);

  if DirHandle = INVALID_HANDLE_VALUE then begin
    ShowMessage('Unable to get handle to directory c:\temp2');
    exit;
  end;

  try
    CompletionPort := CreateIOCompletionPort(DirHandle, 0, 5, 0);
    try
      SetLastError(0);
      ReadResult := ReadDirectoryChangesW(DirHandle
                           , ChangeBuffer
                           , SizeOf(ChangeBuffer)
                           , LongBool(TRUE)
                           , FILE_NOTIFY_CHANGE_LAST_WRITE
                           , BytesReturned
                           , Overlapped
                           , 0);

      LastError := GetLastError;
      if not ReadResult then begin
        ShowMessage(SysErrorMessage(LastError));
        exit;
      end;

      repeat
        Queue := GetQueuedCompletionStatus(CompletionPort
                                         , NumBytes
                                         , Info
                                         , Overlapped
                                         , INFINITE);
        LastError := GetLastError;
        if not Queue then begin
          ShowMessage(Format('GetQueuedCompletionStatus Error %d', [LastError]));
          exit;
        end;

        if Info > 0 then begin
          fni := ChangeBuffer;
          repeat
            OffSet := byte(fni) + fni^.NextEntryOffset;
            fni:= Ptr(Offset);
          until Offset < 1;
        end;

        ReadDirectoryChangesW(DirHandle
                             , ChangeBuffer
                             , SizeOf(ChangeBuffer)
                             , LongBool(FALSE)
                             , FILE_NOTIFY_CHANGE_LAST_WRITE
                             , BytesReturned
                             , Overlapped
                             , 0);

      until Info < 1;

      Dispose(ChangeBuffer);
    finally
      PostQueuedCompletionStatus(CompletionPort, 0, 0, 0);
    end;
  finally
    CloseHandle(DirHandle);
  end;
end;


end.
0
Comment
Question by:pswenson
  • 3
4 Comments
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
what do you want to know?
0
 
LVL 8

Accepted Solution

by:
ZifNab earned 400 total points
Comment Utility
pwenson,

 here is a component which already uses this :

 ftp://ftp.is.co.za/programming/delphi/d30free/fngb2401.exe

 Free with source.

 Why making it difficult? :-)

Regards, Zif.
0
 

Author Comment

by:pswenson
Comment Utility
How did you know the component was at the site?  Is there a directory somewhere?
0
 
LVL 8

Expert Comment

by:ZifNab
Comment Utility
pswenson,

 I was searching for some information about ReadDirectoryChangesW, because I was interested too in this problem. I couldn't find anything usefull, so as last resort I used a searchengine (what normally doesn't help a lot) and by holy there it pointed me out to Delphi Super Page. (Invisible components of D3)

But, DSP has also a search engine. But normally, these specific functions aren't implemented in custom source codes. That's why I didn't checked for components at DSP.

Regards, Zif.
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
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…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

763 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

12 Experts available now in Live!

Get 1:1 Help Now