Solved

File Notification using ReadDirectoryChanges API

Posted on 1998-11-04
4
2,703 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
[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
  • 3
4 Comments
 
LVL 8

Expert Comment

by:ZifNab
ID: 1345641
what do you want to know?
0
 
LVL 8

Accepted Solution

by:
ZifNab earned 400 total points
ID: 1345642
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
ID: 1345643
How did you know the component was at the site?  Is there a directory somewhere?
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1345644
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

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!

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…
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…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
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.

691 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