pswenson
asked on
File Notification using ReadDirectoryChanges API
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(Dir Handle, 0, 5, 0);
try
SetLastError(0);
ReadResult := ReadDirectoryChangesW(DirH andle
, ChangeBuffer
, SizeOf(ChangeBuffer)
, LongBool(TRUE)
, FILE_NOTIFY_CHANGE_LAST_WR ITE
, BytesReturned
, Overlapped
, 0);
LastError := GetLastError;
if not ReadResult then begin
ShowMessage(SysErrorMessag e(LastErro r));
exit;
end;
repeat
Queue := GetQueuedCompletionStatus( Completion Port
, NumBytes
, Info
, Overlapped
, INFINITE);
LastError := GetLastError;
if not Queue then begin
ShowMessage(Format('GetQue uedComplet ionStatus 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(DirH andle
, ChangeBuffer
, SizeOf(ChangeBuffer)
, LongBool(FALSE)
, FILE_NOTIFY_CHANGE_LAST_WR ITE
, BytesReturned
, Overlapped
, 0);
until Info < 1;
Dispose(ChangeBuffer);
finally
PostQueuedCompletionStatus (Completio nPort, 0, 0, 0);
end;
finally
CloseHandle(DirHandle);
end;
end;
end.
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
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
, 0);
if DirHandle = INVALID_HANDLE_VALUE then begin
ShowMessage('Unable to get handle to directory c:\temp2');
exit;
end;
try
CompletionPort := CreateIOCompletionPort(Dir
try
SetLastError(0);
ReadResult := ReadDirectoryChangesW(DirH
, ChangeBuffer
, SizeOf(ChangeBuffer)
, LongBool(TRUE)
, FILE_NOTIFY_CHANGE_LAST_WR
, BytesReturned
, Overlapped
, 0);
LastError := GetLastError;
if not ReadResult then begin
ShowMessage(SysErrorMessag
exit;
end;
repeat
Queue := GetQueuedCompletionStatus(
, NumBytes
, Info
, Overlapped
, INFINITE);
LastError := GetLastError;
if not Queue then begin
ShowMessage(Format('GetQue
exit;
end;
if Info > 0 then begin
fni := ChangeBuffer;
repeat
OffSet := byte(fni) + fni^.NextEntryOffset;
fni:= Ptr(Offset);
until Offset < 1;
end;
ReadDirectoryChangesW(DirH
, ChangeBuffer
, SizeOf(ChangeBuffer)
, LongBool(FALSE)
, FILE_NOTIFY_CHANGE_LAST_WR
, BytesReturned
, Overlapped
, 0);
until Info < 1;
Dispose(ChangeBuffer);
finally
PostQueuedCompletionStatus
end;
finally
CloseHandle(DirHandle);
end;
end;
end.
what do you want to know?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
How did you know the component was at the site? Is there a directory somewhere?
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.
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.