Solved

File Notification using ReadDirectoryChanges API

Posted on 1998-11-04
4
2,681 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
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

Use Case: Protecting a Hybrid Cloud Infrastructure

Microsoft Azure is rapidly becoming the norm in dynamic IT environments. This document describes the challenges that organizations face when protecting data in a hybrid cloud IT environment and presents a use case to demonstrate how Acronis Backup protects all data.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Delphi and Access based Enumeration 9 64
Wincontrol not (correctly) drawn 15 38
How to Get Images From Server using App Tethering 11 29
MS Access from Delphi 31 29
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
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…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

778 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