一篇文章,望对你有用!<br><br><br>在WIN32下用DELPHI侦测目录变化,可用WIN32提供的文件改变通知API来完成。FindFirstChangeNotification, FindNextChangeNotification,FindCloseChangeNotification。<br>在应用程序中调用这些函数时,产生一个监控这个变化的句柄,可用WAIT函数集来等待这个变化。这样,当监控程序运行时,可以达到监控文件变化的动作。更进一步,可把此程序做成一个状态区图标(TRAY)来完成监控。<br><br>Windows在删除、复制、移动、访问文件时并不发送消息,当然截获不到。要截取这些操作过程的唯一办法就是截获API,这又需要你编写Vxd程序了,杀毒软件都是这样作的。你注意一下杀毒软件一般都带有一个vxd程序。光有vxd还不行,还需截获文件API。还有另外一个办法,就是CIH病毒采用的办法,直接跳到系统零层去操作。具体办法如下:<br>一、SIDT指令( 将中断描述符表寄存器IDTR--64位宽,16~47Bit存有中断描述符表IDT基地址--的内容存入指定地址单元)不是特权指令,就是说我们可以在Ring3下执行该指令,获得IDT的基地址,从而修改IDT,增加一个中断门安置我们的中断服务,一旦Ring3程序中产生此中断,VMM就会调用此中断服务程序,而此中断服务程序就运行在Ring0下了。这一点与在DOS下非常相似。<br><br>二、要实现对系统中所有文件I/O操作的实时监视,还要用到另一种关键技-FileHooking,通过挂接一个处理函数,截获所有与文件I/O操作有关的系 统调用。Windows9x使用32位保护模式可安装文件系统(IFS),由可安装文件系统管理器(IFSManager)协调对文件系统和设备的访问,它接收以Win32API函数调用形式向系统发出的文件I/O请求,再将请求转给文件系统驱动程序FSD,由它调用低级别的IOS系统实现最终访问。每个文件I/OAPI调用都有一个特定的FSD函数与之对应,IFSManager负责完成由API到FSD的参数装配工作,在完成文件I/OAPI函数参数的装配之后转相应FSD执行之前,它会调用一个称为FileSystemApiHookFunction的Hooker函数。通过安装自己的Hooker函数,就可以截获系统内所有对文件I/O的API调用,从而实现实时监控。<br>=========================================<br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br> {establish a notification for file name changes on the selected directory}<br> NotificationHandle := FindFirstChangeNotification(PChar(DirectoryListBox1.Directory), FALSE,FILE_NOTIFY_CHANGE_FILE_NAME);<br> {if the notification was set up correctly, modify some UI elements...}<br> if (NotificationHandle <> INVALID_HANDLE_VALUE) then<br> begin<br> Button1.Enabled := TRUE;<br> Button2.Enabled := FALSE;<br> end<br> else<br> begin<br> {...otherwise indicate that there was an error}<br> ShowMessage('There was an error setting the notification');<br> Exit;<br> end;<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br> dwResult: DWORD; // holds the result of waiting on the notification<br> Waiting: Boolean; // loop control variable<br>begin<br> {setup the loop control for a continuous loop}<br> Waiting := TRUE;<br> {indicate that the application is waiting for the change notification to fire}<br> Button1.Enabled := FALSE;<br> StatusBar1.SimpleText := 'Now waiting for a filename change';<br> Application.ProcessMessages;<br> {enter the loop}<br> while Waiting do<br> begin<br> {at this point, the application is suspended until the notification<br> object is signaled that a filename change has occured in the<br> selected directory (this includes file deletions)}<br> dwResult := WaitForSingleObject(NotificationHandle,INFINITE);<br> if (dwResult = WAIT_OBJECT_0) then<br><br> begin<br> {indicate that the notification object was signaled}<br> ShowMessage('The selected directory signaled a filename change');<br><br> {query the user to see if they wish to continue monitoring this<br> directory}<br> if Application.MessageBox('Do you wish to continue monitoring this directory?', 'Continue?', MB_ICONQUESTION or<br> MB_YESNO) = IDYES then<br><br> {if the user wishes to continue monitoring the directory, reset<br> the notification object and continue the loop...}<br> FindNextChangeNotification(NotificationHandle)<br> else<br> {...otherwise break out of the loop}<br> Waiting := FALSE;<br> end;<br> end;<br><br> {close the notification object}<br> FindCloseChangeNotification(NotificationHandle);<br><br> {reset UI elements}<br><br> Button1.Enabled := FALSE;<br> Button2.Enabled := TRUE;<br> StatusBar1.SimpleText := '';<br> FileListBox1.Update;<br>end;<br>===========================================<br>下面是一个监视的控件:<br>unit dirnotify;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Classes,<br> Graphics, Controls, Forms, Dialogs;<br><br>type<br> EDirNotificationError = class(Exception);<br><br> TDirNotify = class;<br> TNotifyFilter = (nfFileName, nfDirName, nfAttributes, nfSize, nfLastWrite,<br> nfSecurity);<br> TNotifyFilters = set of TNotifyFilter;<br><br> TNotificationThread = class(TThread)<br> Owner: TDirNotify;<br> procedure Execute; override;<br> procedure DoChange;<br> end;<br><br> TDirNotify = class(TComponent)<br> private<br> FEnabled: Boolean;<br> FOnChange: TNotifyEvent;<br> FNotificationThread: TNotificationThread;<br> FPath: String;<br> FWatchSubTree: Boolean;<br> FFilter: TNotifyFilters;<br><br> procedure SetEnabled( Value: Boolean );<br> procedure SetOnChange( Value: TNotifyEvent );<br> procedure SetPath( Value: String );<br> procedure SetWatchSubTree( Value: Boolean );<br> procedure SetFilter( Value: TNotifyFilters );<br><br> procedure RecreateThread;<br><br> protected<br> procedure Change;<br> procedure Loaded; override;<br><br> public<br> constructor Create(AOwner: TComponent); override;<br> destructor Destroy; override;<br><br> published<br> property Enabled: Boolean read FEnabled write SetEnabled default True;<br> property OnChange: TNotifyEvent read FOnChange write SetOnChange;<br> property Path: String read FPath write SetPath;<br> property WatchSubTree: Boolean read FWatchSubTree write SetWatchSubTree;<br> property Filter: TNotifyFilters read FFilter write SetFilter default [nfFileName, nfDirName, nfAttributes, nfLastWrite, nfSecurity];<br> end;<br><br><br>procedure Register;<br><br>implementation<br><br>const<br> LASTERRORTEXTLENGTH = 500;<br><br>var<br> LastErrorText: array [0..LASTERRORTEXTLENGTH] of char;<br><br><br>function GetLastErrorText: PChar;<br>begin<br> FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,<br> nil, GetLastError, 0, LastErrorText, LASTERRORTEXTLENGTH, nil );<br> Result := LastErrorText;<br>end;<br><br><br>procedure TNotificationThread.Execute;<br>var<br> h: THandle;<br> nf: Longint;<br> wst: LongBool;<br>begin<br> nf := 0;<br> if (nfFileName in Owner.Filter) then nf := FILE_NOTIFY_CHANGE_FILE_NAME;<br> if (nfDirName in Owner.Filter) then nf := nf or FILE_NOTIFY_CHANGE_DIR_NAME;<br> if (nfAttributes in Owner.Filter) then nf := nf or FILE_NOTIFY_CHANGE_ATTRIBUTES;<br> if (nfSize in Owner.Filter) then nf := nf or FILE_NOTIFY_CHANGE_SIZE;<br> if (nfLastWrite in Owner.Filter) then nf := nf or FILE_NOTIFY_CHANGE_LAST_WRITE;<br> if (nfSecurity in Owner.Filter) then nf := nf or FILE_NOTIFY_CHANGE_SECURITY;<br><br> // yeahh, this one is stupid but Win98 malfunctions in any other value than 0 or 1<br> if Owner.FWatchSubTree then wst := Longbool(1)<br> else wst := Longbool(0);<br><br> h := FindFirstChangeNotification( Pointer(Owner.Path), wst, nf );<br> if (h = INVALID_HANDLE_VALUE) then<br> raise EDirNotificationError.Create( GetLastErrorText );<br><br> repeat<br> if (WaitForSingleObject( h, 1000 ) = WAIT_OBJECT_0) then<br> begin<br> Synchronize(DoChange);<br><br> if not FindNextChangeNotification( h ) then<br> raise EDirNotificationError.Create( GetLastErrorText );<br> end;<br> until Terminated;<br>end;<br><br><br>procedure TNotificationThread.DoChange;<br>begin<br> Owner.Change;<br>end;<br><br><br>constructor TDirNotify.Create(AOwner: TComponent);<br>begin<br> inherited Create(AOwner);<br><br> FEnabled := True;<br> FFilter := [nfFileName];<br>end;<br><br><br>destructor TDirNotify.Destroy;<br>begin<br> FNotificationThread.Free;<br> inherited Destroy;<br>end;<br><br>procedure TDirNotify.Loaded;<br>begin<br> inherited;<br><br> RecreateThread;<br>end;<br><br><br>procedure TDirNotify.SetEnabled(Value: Boolean);<br>begin<br> if Value <> FEnabled then<br> begin<br> FEnabled := Value;<br><br> RecreateThread;<br> end;<br>end;<br><br><br>procedure TDirNotify.SetPath( Value: String );<br>begin<br> if Value <> FPath then<br> begin<br> FPath := Value;<br> RecreateThread;<br> end;<br>end;<br><br><br>procedure TDirNotify.SetWatchSubTree( Value: Boolean );<br>begin<br> if Value <> FWatchSubTree then<br> begin<br> FWatchSubTree := Value;<br> RecreateThread;<br> end;<br>end;<br><br><br>procedure TDirNotify.SetFilter( Value: TNotifyFilters );<br>begin<br> if Value <> FFilter then<br> begin<br> FFilter := Value;<br> RecreateThread;<br> end;<br>end;<br><br><br>procedure TDirNotify.SetOnChange(Value: TNotifyEvent);<br>begin<br> FOnChange := Value;<br>end;<br><br><br>procedure TDirNotify.Change;<br>begin<br> if Assigned(FOnChange) then<br> FOnChange(Self);<br>end;<br><br><br>procedure TDirNotify.RecreateThread;<br>begin<br> // destroy thread<br> FNotificationThread.Free;<br> FNotificationThread := nil;<br><br> if FEnabled and not(csDesigning in ComponentState)<br> and not(csLoading in ComponentState) and (FPath <> '') then<br> begin<br> // create thread<br> FNotificationThread := TNotificationThread.Create(True);<br> FNotificationThread.Owner := self;<br> FNotificationThread.Resume;<br> end;<br>end;<br><br><br>procedure Register;<br>begin<br> RegisterComponents('System', [TDirNotify]);<br>end;<br><br>end.<br>