ReadDirectoryChangesw使用问题 下载一个控件, 绝对满足需要 :)TOxygenDirectorySpy17 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 做了个谢绝安装版的http://blog.csdn.net/simonhehe/article/details/8601296 用dir看一下文件系统的属性改了没有。NTFS更新文件属性比较慢的。 以前写的一个组件供参考unit uDirectoryMonitor;//==============================================================================// Unit Name: uDirectoryMonitor// Author : ysai// Date : 2006-11-28 // Purpose : 目录监视器// History ://==============================================================================interfaceuses Windows, Messages, SysUtils, Classes;const NotificationBuffer_Size = 1024 * 1024;type TFileAction = ( faAdded = 1, faRemoved, faModifyed, faRenamedOldName, faRenamedNewName ); TMonitorType = (mtDirName, mtAttrib, mtSize, mtSecurity, mtCreationDate, mtLastAccess, mtLastWrite, mtFileName); TMonitorTypes = set of TMonitorType; TDirectoryMonitorChangeEvent = procedure(Sender: TObject; FileAction : TFileAction; FileName : string) of object; TDirectoryMonitor = class(TComponent) private FDirectoryHandle: THandle; FNotificationBuffer: array[0..NotificationBuffer_Size] of Byte; FWatchThread: TThread; FNotifyFilter: DWORD; FOverlapped: TOverlapped; FPOverlapped: POverlapped; FBytesWritten: DWORD; FCompletionPort: THandle; FActive: Boolean; FWatchSubTree: Boolean; FMonitorDirName: Boolean; FMonitorAttributes: Boolean; FMonitorSize: Boolean; FMonitorSecurity: Boolean; FMonitorCreationDate: Boolean; FMonitorLastAccess: Boolean; FMonitorLastWrite: Boolean; FMonitorFileName: Boolean; FDirectory: string; FOnChange: TDirectoryMonitorChangeEvent; private function GetMonitorTypes: TMonitorTypes; procedure SetMonitorTypes(const Value: TMonitorTypes); protected property WatchThread : TThread read FWatchThread; procedure DoChange( const FileAction : TFileAction; const FileName : string ); procedure Start; procedure Stop; procedure SetActive(const Value: Boolean); public property Active : Boolean read FActive Write SetActive; constructor Create(AOwner: TComponent);override; destructor Destroy; override; published property Directory : string read FDirectory Write FDirectory; property WatchSubTree : Boolean read FWatchSubTree Write FWatchSubTree default False; property MonitorFileName : Boolean read FMonitorFileName Write FMonitorFileName default False; property MonitorDirName : Boolean read FMonitorDirName Write FMonitorDirName default False; property MonitorAttributes : Boolean read FMonitorAttributes Write FMonitorAttributes default False; property MonitorSize : Boolean read FMonitorSize Write FMonitorSize default False; property MonitorLastWrite : Boolean read FMonitorLastWrite Write FMonitorLastWrite default False; property MonitorLastAccess : Boolean read FMonitorLastAccess Write FMonitorLastAccess default False; property MonitorCreationDate : Boolean read FMonitorCreationDate Write FMonitorCreationDate default False; property MonitorSecurity : Boolean read FMonitorSecurity Write FMonitorSecurity default False; property MonitorTypes : TMonitorTypes read GetMonitorTypes write SetMonitorTypes; property OnChange : TDirectoryMonitorChangeEvent read FOnChange Write FOnChange; end;procedure Register;implementationtype PFileNotifyInformation = ^TFileNotifyInformation; TFileNotifyInformation = record NextEntryOffset: DWORD; Action: DWORD; FileNameLength: DWORD; FileName: array[0..0] of WideChar; end; TWaitThread = class(TThread) private FOwner : TDirectoryMonitor; procedure HandleEvent; protected procedure Execute; override; public constructor Create(Owner: TDirectoryMonitor); end;const FILE_LIST_DIRECTORY = $0001;{ TDirectoryMonitor }constructor TDirectoryMonitor.Create(AOwner: TComponent);begin inherited Create(AOwner); FCompletionPort := 0; FDirectoryHandle := 0; FPOverlapped := @FOverlapped; ZeroMemory(@FOverlapped, SizeOf(FOverlapped));end;destructor TDirectoryMonitor.Destroy;begin Active := False; inherited;end;procedure TDirectoryMonitor.DoChange( const FileAction : TFileAction; const FileName : string );var fname : string;begin if Pos(':', FileName) > 0 then fname := FileName else if FDirectory[Length(FDirectory)] = '\' then fname := FDirectory + FileName else fname := FDirectory + '\' + FileName; if Assigned(FOnChange) then FOnChange(Self, FileAction, fname);end;function TDirectoryMonitor.GetMonitorTypes: TMonitorTypes;begin result := []; if FMonitorAttributes then result := result + [mtAttrib]; if FMonitorCreationDate then result := result + [mtCreationDate]; if FMonitorDirName then result := result + [mtDirName]; if FMonitorFileName then result := result + [mtFileName]; if FMonitorLastAccess then result := result + [mtLastAccess]; if FMonitorLastWrite then result := result + [mtLastWrite]; if FMonitorSecurity then result := result + [mtSecurity]; if FMonitorSize then result := result + [mtSize];end;procedure TDirectoryMonitor.SetMonitorTypes(const Value: TMonitorTypes);begin MonitorAttributes := mtAttrib in Value; MonitorCreationDate := mtCreationDate in Value; MonitorDirName := mtDirName in Value; MonitorFileName := mtFileName in Value; MonitorLastAccess := mtLastAccess in Value; MonitorLastWrite := mtLastWrite in Value; MonitorSecurity := mtSecurity in Value; MonitorSize := mtSize in Value;end;procedure TDirectoryMonitor.SetActive(const Value: Boolean);begin if Value <> FActive then begin if Value then Start else Stop; FActive := Value; end;end;procedure TDirectoryMonitor.Start;begin FNotifyFilter := 0; if MonitorFileName then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_FILE_NAME; if MonitorDirName then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_DIR_NAME; if MonitorAttributes then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_ATTRIBUTES; if MonitorSize then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SIZE; if MonitorLastWrite then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_WRITE; if MonitorLastAccess then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_ACCESS; if MonitorCreationDate then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_CREATION; if MonitorSecurity then FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SECURITY; if FNotifyFilter = 0 then begin raise Exception.Create('请选择监视内容!'); end; FDirectoryHandle := CreateFile( PChar(FDirectory), 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 FDirectoryHandle = INVALID_HANDLE_VALUE then begin FDirectoryHandle := 0; raise Exception.Create(SysErrorMessage(GetLastError)); end; FCompletionPort := CreateIoCompletionPort(FDirectoryHandle, 0, Longint(pointer(self)), 0); ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer)); FBytesWritten := 0; if not ReadDirectoryChanges( FDirectoryHandle, @FNotificationBuffer, SizeOf(FNotificationBuffer), WatchSubTree, FNotifyFilter, @FBytesWritten, @FOverlapped, nil ) then begin CloseHandle(FDirectoryHandle); FDirectoryHandle := 0; CloseHandle(FCompletionPort); FCompletionPort := 0; raise Exception.Create(SysErrorMessage(GetLastError)); end; FWatchThread := TWaitThread.Create(Self); {$IFDEF DELPHI2009_UP} TWaitThread(FWatchThread).Start; {$ELSE} TWaitThread(FWatchThread).Resume; {$ENDIF}end;procedure TDirectoryMonitor.Stop;begin if FCompletionPort = 0 then exit; PostQueuedCompletionStatus(FCompletionPort, 0, 0, nil); FWatchThread.WaitFor; FWatchThread.Free; FWatchThread := nil; CloseHandle(FDirectoryHandle); FDirectoryHandle := 0; CloseHandle(FCompletionPort); FCompletionPort := 0;end;{ TWaitThread }constructor TWaitThread.Create(Owner: TDirectoryMonitor);begin inherited Create(True); FOwner := Owner; FreeOnTerminate := False;end;procedure TWaitThread.Execute;var numBytes: DWORD; //cbOffset: DWORD; CompletionKey: DWORD;begin while not Terminated do begin GetQueuedCompletionStatus(FOwner.FCompletionPort, numBytes, CompletionKey, FOwner.FPOverlapped, INFINITE); if CompletionKey <> 0 then begin Synchronize(HandleEvent); FOwner.FBytesWritten := 0; ZeroMemory(@FOwner.FNotificationBuffer, SizeOf(FOwner.FNotificationBuffer)); ReadDirectoryChanges( FOwner.FDirectoryHandle, @FOwner.FNotificationBuffer, SizeOf(FOwner.FNotificationBuffer), FOwner.WatchSubTree, FOwner.FNotifyFilter, @FOwner.FBytesWritten, @FOwner.FOverlapped, nil ); end else Terminate; end;end;procedure TWaitThread.HandleEvent;var FileOpNotification: PFileNotifyInformation; Offset: Longint;begin Pointer(FileOpNotification) := @FOwner.FNotificationBuffer[0]; repeat Offset := FileOpNotification^.NextEntryOffset; FOwner.DoChange( TFileAction(FileOpNotification^.Action), WideCharLenToString(@(FileOpNotification^.FileName), FileOpNotification^.FileNameLength div 2) ); Pointer(FileOpNotification) := Pointer(Integer(FileOpNotification) + Offset); until Offset = 0;end;procedure Register;begin RegisterComponents('System', [TDirectoryMonitor]);end;end. 应该不会漏,都依赖于操作系统的API,如果系统漏了就没办法了可以写个小程序测试一下unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, uDirectoryMonitor, StdCtrls;type TForm1 = class(TForm) Button1: TButton; lst: TListBox; procedure Button1Click(Sender: TObject); private procedure OnChange(Sender: TObject; FileAction : TFileAction; FileName : string); public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}const TFileActionNames : array[faAdded..faRenamedNewName] of string = ( 'Added', 'Removed', 'Modifyed', 'RenamedOldName', 'RenamedNewName' );procedure TForm1.Button1Click(Sender: TObject);begin with TDirectoryMonitor.Create(Self) do begin Directory := 'F:\Test'; WatchSubTree := True; MonitorTypes := [mtDirName, mtAttrib, mtSize, mtSecurity, mtCreationDate, mtLastAccess, mtLastWrite, mtFileName]; OnChange := Self.OnChange; Active := True; end;end;procedure TForm1.OnChange(Sender: TObject; FileAction: TFileAction; FileName: string);begin if FileAction = faAdded then lst.Items.Add(Format('%s - %s', [TFileActionNames[FileAction], FileName])); Caption := IntToStr(lst.Items.Count);end;end.往测试文件夹写入大量小文件,看有没有丢消息,我这WIN7 64是没发现漏掉的 http://code.google.com/p/winmod/wiki/UnderstandingReadDirectoryChangesW_CN这篇文章指出......消失丢失可能是因为你的程序处理消息的速度不够快如上我写的组件,因为是Synchronize调用触发事件方式处理消息,所以如果你的主线程卡住,那么就可能丢失消息.可能的解决方案是:在线程中尽量简化ReadDirectoryChanges后的操作,把读到的消息都丢到一个队列,然后用PostMessage或其它异步方式通知主线程来处理消息队列 刚试过 你这个确实没有漏掉变动消息, 在codeproject上看到过一个监控目录的代码,也是不会漏掉消息,但我把他改成DELPHI版本的就会漏掉了,原理和你上面贴的代码一样都是使用的ReadDirectoryChangesW 通过完成端口来 捕获文件的变动信息~~~也是使用线程来等待完成端口通知.应该不存在卡死的情况... 重命名无法获取新名字的问题是FILE_NOTIFY_INFORMATION没有读完注意FILE_NOTIFY_INFORMATION->NextEntryOffset 这个参数.http://msdn.microsoft.com/en-us/library/windows/desktop/aa364391(v=vs.85).aspx 请朋友们给个D7下的函数:PWideChar转PAnsichar的 麻烦高手解析一下下面的代码,谢谢 TList与控件应用,涉及Delphi基础,请您解答! 怎样在DELPHI里响应COM接口的事件? 急啊,关系饭碗问题啊!! 上传文件乱吗 TButtonLayout在代码中赋值却说"Undeclared..." 怎么办? 找 将Delphi源文件按照Delphi中的标记方式保存为Html文件的工具 2000下使用QUICKREPORT打印走纸的问题 为庆祝本人第一次进入专家榜(第21位),特大叫三声嘎!嘎!嘎!。。。。。。 请高手指点 如何判断word文档关闭问题 视频格式转化问题
http://blog.csdn.net/simonhehe/article/details/8601296
unit uDirectoryMonitor;
//==============================================================================
// Unit Name: uDirectoryMonitor
// Author : ysai
// Date : 2006-11-28
// Purpose : 目录监视器
// History :
//==============================================================================interfaceuses
Windows, Messages, SysUtils, Classes;const
NotificationBuffer_Size = 1024 * 1024;type
TFileAction = (
faAdded = 1,
faRemoved,
faModifyed,
faRenamedOldName,
faRenamedNewName
);
TMonitorType = (mtDirName, mtAttrib, mtSize, mtSecurity, mtCreationDate,
mtLastAccess, mtLastWrite, mtFileName);
TMonitorTypes = set of TMonitorType;
TDirectoryMonitorChangeEvent =
procedure(Sender: TObject; FileAction : TFileAction; FileName : string) of object; TDirectoryMonitor = class(TComponent)
private
FDirectoryHandle: THandle;
FNotificationBuffer: array[0..NotificationBuffer_Size] of Byte;
FWatchThread: TThread;
FNotifyFilter: DWORD;
FOverlapped: TOverlapped;
FPOverlapped: POverlapped;
FBytesWritten: DWORD;
FCompletionPort: THandle;
FActive: Boolean;
FWatchSubTree: Boolean;
FMonitorDirName: Boolean;
FMonitorAttributes: Boolean;
FMonitorSize: Boolean;
FMonitorSecurity: Boolean;
FMonitorCreationDate: Boolean;
FMonitorLastAccess: Boolean;
FMonitorLastWrite: Boolean;
FMonitorFileName: Boolean;
FDirectory: string;
FOnChange: TDirectoryMonitorChangeEvent;
private
function GetMonitorTypes: TMonitorTypes;
procedure SetMonitorTypes(const Value: TMonitorTypes);
protected
property WatchThread : TThread read FWatchThread; procedure DoChange(
const FileAction : TFileAction;
const FileName : string
);
procedure Start;
procedure Stop;
procedure SetActive(const Value: Boolean);
public
property Active : Boolean read FActive Write SetActive; constructor Create(AOwner: TComponent);override;
destructor Destroy; override;
published
property Directory : string read FDirectory Write FDirectory; property WatchSubTree : Boolean read FWatchSubTree Write FWatchSubTree default False; property MonitorFileName : Boolean read FMonitorFileName Write FMonitorFileName default False;
property MonitorDirName : Boolean read FMonitorDirName Write FMonitorDirName default False;
property MonitorAttributes : Boolean read FMonitorAttributes Write FMonitorAttributes default False;
property MonitorSize : Boolean read FMonitorSize Write FMonitorSize default False;
property MonitorLastWrite : Boolean read FMonitorLastWrite Write FMonitorLastWrite default False;
property MonitorLastAccess : Boolean read FMonitorLastAccess Write FMonitorLastAccess default False;
property MonitorCreationDate : Boolean read FMonitorCreationDate Write FMonitorCreationDate default False;
property MonitorSecurity : Boolean read FMonitorSecurity Write FMonitorSecurity default False; property MonitorTypes : TMonitorTypes read GetMonitorTypes write SetMonitorTypes; property OnChange : TDirectoryMonitorChangeEvent read FOnChange Write FOnChange;
end;procedure Register;implementationtype
PFileNotifyInformation = ^TFileNotifyInformation;
TFileNotifyInformation = record
NextEntryOffset: DWORD;
Action: DWORD;
FileNameLength: DWORD;
FileName: array[0..0] of WideChar;
end; TWaitThread = class(TThread)
private
FOwner : TDirectoryMonitor;
procedure HandleEvent;
protected
procedure Execute; override;
public
constructor Create(Owner: TDirectoryMonitor);
end;const
FILE_LIST_DIRECTORY = $0001;{ TDirectoryMonitor }constructor TDirectoryMonitor.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCompletionPort := 0;
FDirectoryHandle := 0;
FPOverlapped := @FOverlapped;
ZeroMemory(@FOverlapped, SizeOf(FOverlapped));
end;destructor TDirectoryMonitor.Destroy;
begin
Active := False;
inherited;
end;procedure TDirectoryMonitor.DoChange(
const FileAction : TFileAction;
const FileName : string
);
var
fname : string;
begin
if Pos(':', FileName) > 0 then
fname := FileName
else
if FDirectory[Length(FDirectory)] = '\' then
fname := FDirectory + FileName
else
fname := FDirectory + '\' + FileName;
if Assigned(FOnChange) then
FOnChange(Self, FileAction, fname);
end;function TDirectoryMonitor.GetMonitorTypes: TMonitorTypes;
begin
result := [];
if FMonitorAttributes then result := result + [mtAttrib];
if FMonitorCreationDate then result := result + [mtCreationDate];
if FMonitorDirName then result := result + [mtDirName];
if FMonitorFileName then result := result + [mtFileName];
if FMonitorLastAccess then result := result + [mtLastAccess];
if FMonitorLastWrite then result := result + [mtLastWrite];
if FMonitorSecurity then result := result + [mtSecurity];
if FMonitorSize then result := result + [mtSize];
end;procedure TDirectoryMonitor.SetMonitorTypes(const Value: TMonitorTypes);
begin
MonitorAttributes := mtAttrib in Value;
MonitorCreationDate := mtCreationDate in Value;
MonitorDirName := mtDirName in Value;
MonitorFileName := mtFileName in Value;
MonitorLastAccess := mtLastAccess in Value;
MonitorLastWrite := mtLastWrite in Value;
MonitorSecurity := mtSecurity in Value;
MonitorSize := mtSize in Value;
end;procedure TDirectoryMonitor.SetActive(const Value: Boolean);
begin
if Value <> FActive then
begin
if Value then
Start
else
Stop;
FActive := Value;
end;
end;procedure TDirectoryMonitor.Start;
begin
FNotifyFilter := 0;
if MonitorFileName then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_FILE_NAME;
if MonitorDirName then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_DIR_NAME;
if MonitorAttributes then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_ATTRIBUTES;
if MonitorSize then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SIZE;
if MonitorLastWrite then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_WRITE;
if MonitorLastAccess then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_LAST_ACCESS;
if MonitorCreationDate then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_CREATION;
if MonitorSecurity then
FNotifyFilter := FNotifyFilter or FILE_NOTIFY_CHANGE_SECURITY; if FNotifyFilter = 0 then
begin
raise Exception.Create('请选择监视内容!');
end; FDirectoryHandle := CreateFile(
PChar(FDirectory),
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 FDirectoryHandle = INVALID_HANDLE_VALUE then
begin
FDirectoryHandle := 0;
raise Exception.Create(SysErrorMessage(GetLastError));
end;
FCompletionPort := CreateIoCompletionPort(FDirectoryHandle, 0, Longint(pointer(self)), 0);
ZeroMemory(@FNotificationBuffer, SizeOf(FNotificationBuffer));
FBytesWritten := 0;
if not ReadDirectoryChanges(
FDirectoryHandle,
@FNotificationBuffer,
SizeOf(FNotificationBuffer),
WatchSubTree,
FNotifyFilter,
@FBytesWritten,
@FOverlapped,
nil
) then
begin
CloseHandle(FDirectoryHandle);
FDirectoryHandle := 0;
CloseHandle(FCompletionPort);
FCompletionPort := 0;
raise Exception.Create(SysErrorMessage(GetLastError));
end;
FWatchThread := TWaitThread.Create(Self);
{$IFDEF DELPHI2009_UP}
TWaitThread(FWatchThread).Start;
{$ELSE}
TWaitThread(FWatchThread).Resume;
{$ENDIF}
end;procedure TDirectoryMonitor.Stop;
begin
if FCompletionPort = 0 then
exit;
PostQueuedCompletionStatus(FCompletionPort, 0, 0, nil);
FWatchThread.WaitFor;
FWatchThread.Free;
FWatchThread := nil;
CloseHandle(FDirectoryHandle);
FDirectoryHandle := 0;
CloseHandle(FCompletionPort);
FCompletionPort := 0;
end;{ TWaitThread }constructor TWaitThread.Create(Owner: TDirectoryMonitor);
begin
inherited Create(True);
FOwner := Owner;
FreeOnTerminate := False;
end;procedure TWaitThread.Execute;
var
numBytes: DWORD;
//cbOffset: DWORD;
CompletionKey: DWORD;
begin
while not Terminated do
begin
GetQueuedCompletionStatus(FOwner.FCompletionPort, numBytes, CompletionKey, FOwner.FPOverlapped, INFINITE);
if CompletionKey <> 0 then
begin
Synchronize(HandleEvent);
FOwner.FBytesWritten := 0;
ZeroMemory(@FOwner.FNotificationBuffer, SizeOf(FOwner.FNotificationBuffer));
ReadDirectoryChanges(
FOwner.FDirectoryHandle,
@FOwner.FNotificationBuffer,
SizeOf(FOwner.FNotificationBuffer),
FOwner.WatchSubTree,
FOwner.FNotifyFilter,
@FOwner.FBytesWritten,
@FOwner.FOverlapped,
nil
);
end
else
Terminate;
end;
end;procedure TWaitThread.HandleEvent;
var
FileOpNotification: PFileNotifyInformation;
Offset: Longint;
begin
Pointer(FileOpNotification) := @FOwner.FNotificationBuffer[0];
repeat
Offset := FileOpNotification^.NextEntryOffset;
FOwner.DoChange(
TFileAction(FileOpNotification^.Action),
WideCharLenToString(@(FileOpNotification^.FileName), FileOpNotification^.FileNameLength div 2)
);
Pointer(FileOpNotification) := Pointer(Integer(FileOpNotification) + Offset);
until Offset = 0;
end;procedure Register;
begin
RegisterComponents('System', [TDirectoryMonitor]);
end;end.
可以写个小程序测试一下
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
uDirectoryMonitor, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
lst: TListBox;
procedure Button1Click(Sender: TObject);
private
procedure OnChange(Sender: TObject; FileAction : TFileAction; FileName : string);
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}const
TFileActionNames : array[faAdded..faRenamedNewName] of string = (
'Added',
'Removed',
'Modifyed',
'RenamedOldName',
'RenamedNewName'
);procedure TForm1.Button1Click(Sender: TObject);
begin
with TDirectoryMonitor.Create(Self) do
begin
Directory := 'F:\Test';
WatchSubTree := True;
MonitorTypes := [mtDirName, mtAttrib, mtSize, mtSecurity, mtCreationDate,
mtLastAccess, mtLastWrite, mtFileName];
OnChange := Self.OnChange;
Active := True;
end;
end;procedure TForm1.OnChange(Sender: TObject; FileAction: TFileAction;
FileName: string);
begin
if FileAction = faAdded then
lst.Items.Add(Format('%s - %s', [TFileActionNames[FileAction], FileName]));
Caption := IntToStr(lst.Items.Count);
end;end.往测试文件夹写入大量小文件,看有没有丢消息,我这WIN7 64是没发现漏掉的
这篇文章指出......消失丢失可能是因为你的程序处理消息的速度不够快如上我写的组件,因为是Synchronize调用触发事件方式处理消息,所以如果你的主线程卡住,那么就可能丢失消息.可能的解决方案是:在线程中尽量简化ReadDirectoryChanges后的操作,把读到的消息都丢到一个队列,然后用PostMessage或其它异步方式通知主线程来处理消息队列
刚试过 你这个确实没有漏掉变动消息, 在codeproject上看到过一个监控目录的代码,也是不会漏掉消息,但我把他改成DELPHI版本的就会漏掉了,原理和你上面贴的代码一样都是使用的ReadDirectoryChangesW 通过完成端口来 捕获文件的变动信息~~~也是使用线程来等待完成端口通知.应该不存在卡死的情况...
注意FILE_NOTIFY_INFORMATION->NextEntryOffset 这个参数.http://msdn.microsoft.com/en-us/library/windows/desktop/aa364391(v=vs.85).aspx