我的个人看法:
1、因为是某类文件,而且通过扩展名,那么就可以知道这个扩展名在系统注册的对应引用程序,所以看 看能不能想办法监控那个程序
2、现在似乎钩子很流行,所以有人建议用文件钩子,我不会,如果你会或许是个办法
http://www.delphibbs.com/delphibbs/dispq.asp?LID=130925
我用BCB写了一个监视某个目录(如果要监视一个已经存在文件原理是一样的,而且
应该说更简单一些)
调用了以下API:
FindFirstChangeNotification()
FindNextChangeNotification()
WaitForSingleObject()
三个函数的具体含义和参数请参看MSDN或WIN32 HELP
然后为了保证在监视的时候避免死锁,而无法做其他的控制操作,因此我采用了线程
来设计这些功能,我将部分代码贴出来,如果需要,可以找我全部代码.
//--以下是用于监视的函数-----------START------
bool WatchResume(HANDLE hWatched,unsigned int interval)
{
DWORD rWatch;
//pathname="C://inetpub";
rWatch=FindNextChangeNotification(hWatched);
do
{
rWatch = WaitForSingleObject(hWatched, interval);
}while((rWatch!=0)&&(!terminateFlag));
return rWatch;
}
HANDLE WatchCreate(LPCTSTR pathname,unsigned long flags)
{
return FindFirstChangeNotification(pathname, true,flags);
}
DWORD WatchDirectory(HANDLE hWatched,unsigned long interval)
{
DWORD rWatched;
do
{
rWatched=WaitForSingleObject(hWatched,interval);
}while((rWatched!=0)&&(!terminateFlag));
return rWatched;
}
void WatchDelete(HANDLE hWatched)
{
DWORD rWatched;
terminateFlag=true;
FindCloseChangeNotification(hWatched);
}
//-----------以上是用于监视的函数-------END
//与相关线程相关的函数
__fastcall TWatchThread::TWatchThread(int theFlag):TThread(true)
{
FreeOnTerminate=true;
flag=theFlag;
logmsg="";
Resume();
}
void __fastcall TWatchThread::Execute(void)
{
DWORD watchStatus;
WIN32_FIND_DATA FileInfo;
HANDLE FileHandle;
unsigned int i;
static FILETIME WriteTime;
terminateFlag=false;
if (flag==1){ //监视文件的创建,重命名,删除,覆盖
hWatched = WatchCreate("C://InetPub",FILE_NOTIFY_CHANGE_FILE_NAME);
watchStatus = WatchDirectory(hWatched, 100);
if (watchStatus==0){
logmsg="有文件被创建,重命名,删除或者覆盖了!";
Synchronize(Writelog);
}
}else
if(flag==2){ //监视文件的修改
hWatched = WatchCreate("C://InetPub",FILE_NOTIFY_CHANGE_LAST_WRITE);
watchStatus = WatchDirectory(hWatched, 100);
if (watchStatus==0){
//ShowMessage("文件变化了!"
;
logmsg="有文件的内容被被修改了!";
Synchronize(Writelog);
}
}
}
void __fastcall TWatchThread::Writelog(void)
{
Form1->Memo1->Lines->Add(logmsg);
}
//在头文件中的声明
class TWatchThread
ublic TThread
{
public:
__fastcall TWatchThread(int theFlag);
private:
int flag;
char *logmsg;
void __fastcall Execute(void);
void __fastcall Writelog(void);
};
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
TMemo *Memo1;
TButton *Button3;
TButton *Button4;
TLabel *Label1;
TClientSocket *ClientSocket1;
TPanel *Panel1;
TComboBox *ComboBox1;
TLabel *Label2;
TMemo *Memo2;
TTimer *Timer1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button4Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall Timer1Timer(TObject *Sender);
private: // User declarations
TWatchThread *WatchWrite,*WatchChange;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//启动线程
WatchWrite=new TWatchThread(1);
WatchChange=new TWatchThread(2);
目前我可以实时监视任何目录下的文件的变化,但是我现在缺乏一个方案:
即发现哪个文件变化了,只能知道我监视的目录下有文件变化了
还希望各位大虾帮忙解决
http://www.delphibbs.com/delphibbs/dispq.asp?LID=840658
在WIN32下用DELPHI侦测目录变化,可用WIN32提供的文件改变通知API来完成。FindFirstChangeNotification, FindNextChangeNotification,FindCloseChangeNotification。
在应用程序中调用这些函数时,产生一个监控这个变化的句柄,可用WAIT函数集来等待这个变化。这样,当监控程序运行时,可以达到监控文件变化的动作。更进一步,可把此程序做成一个状态区图标(TRAY)来完成监控。
Windows在删除、复制、移动、访问文件时并不发送消息,当然截获不到。要截取这些操作过程的唯一办法就是截获API,这又需要你编写Vxd程序了,杀毒软件都是这样作的。你注意一下杀毒软件一般都带有一个vxd程序。光有vxd还不行,还需截获文件API。还有另外一个办法,就是CIH病毒采用的办法,直接跳到系统零层去操作。具体办法如下:
一、SIDT指令( 将中断描述符表寄存器IDTR--64位宽,16~47Bit存有中断描述符表IDT基地址--的内容存入指定地址单元)不是特权指令,就是说我们可以在Ring3下执行该指令,获得IDT的基地址,从而修改IDT,增加一个中断门安置我们的中断服务,一旦Ring3程序中产生此中断,VMM就会调用此中断服务程序,而此中断服务程序就运行在Ring0下了。这一点与在DOS下非常相似。
二、要实现对系统中所有文件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调用,从而实现实时监控。
=========================================
procedure TForm1.Button2Click(Sender: TObject);
begin
{establish a notification for file name changes on the selected directory}
NotificationHandle := FindFirstChangeNotification(PChar(DirectoryListBox1.Directory), FALSE,FILE_NOTIFY_CHANGE_FILE_NAME);
{if the notification was set up correctly, modify some UI elements...}
if (NotificationHandle <> INVALID_HANDLE_VALUE) then
begin
Button1.Enabled := TRUE;
Button2.Enabled := FALSE;
end
else
begin
{...otherwise indicate that there was an error}
ShowMessage('There was an error setting the notification');
Exit;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
dwResult: DWORD;
// holds the result of waiting on the notification
Waiting: Boolean;
// loop control variable
begin
{setup the loop control for a continuous loop}
Waiting := TRUE;
{indicate that the application is waiting for the change notification to fire}
Button1.Enabled := FALSE;
StatusBar1.SimpleText := 'Now waiting for a filename change';
Application.ProcessMessages;
{enter the loop}
while Waitingdo
begin
{at this point, the application is suspended until the notification
object is signaled that a filename change has occured in the
selected directory (this includes file deletions)}
dwResult := WaitForSingleObject(NotificationHandle,INFINITE);
if (dwResult = WAIT_OBJECT_0) then
begin
{indicate that the notification object was signaled}
ShowMessage('The selected directory signaled a filename change');
{query the user to see if they wish to continue monitoring this
directory}
if Application.MessageBox('Do you wish to continue monitoring this directory?', 'Continue?', MB_ICONQUESTION or
MB_YESNO) = IDYES then
{if the user wishes to continue monitoring the directory, reset
the notification object and continue the loop...}
FindNextChangeNotification(NotificationHandle)
else
{...otherwise break out of the loop}
Waiting := FALSE;
end;
end;
{close the notification object}
FindCloseChangeNotification(NotificationHandle);
{reset UI elements}
Button1.Enabled := FALSE;
Button2.Enabled := TRUE;
StatusBar1.SimpleText := '';
FileListBox1.Update;
end;
===========================================
下面是一个监视的控件:
unit dirnotify;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs;
type
EDirNotificationError = class(Exception);
TDirNotify = class;
TNotifyFilter = (nfFileName, nfDirName, nfAttributes, nfSize, nfLastWrite,
nfSecurity);
TNotifyFilters = set of TNotifyFilter;
TNotificationThread = class(TThread)
Owner: TDirNotify;
procedure Execute;
override;
proceduredo
Change;
end;
TDirNotify = class(TComponent)
private
FEnabled: Boolean;
FOnChange: TNotifyEvent;
FNotificationThread: TNotificationThread;
FPath: String;
FWatchSubTree: Boolean;
FFilter: TNotifyFilters;
procedure SetEnabled( Value: Boolean );
procedure SetOnChange( Value: TNotifyEvent );
procedure SetPath( Value: String );
procedure SetWatchSubTree( Value: Boolean );
procedure SetFilter( Value: TNotifyFilters );
procedure RecreateThread;
protected
procedure Change;
procedure Loaded;
override;
public
constructor Create(AOwner: TComponent);
override;
destructor Destroy;
override;
published
property Enabled: Boolean read FEnabled write SetEnabled default True;
property OnChange: TNotifyEvent read FOnChange write SetOnChange;
property Path: String read FPath write SetPath;
property WatchSubTree: Boolean read FWatchSubTree write SetWatchSubTree;
property Filter: TNotifyFilters read FFilter write SetFilter default [nfFileName, nfDirName, nfAttributes, nfLastWrite, nfSecurity];
end;
procedure Register;
implementation
const
LASTERRORTEXTLENGTH = 500;
var
LastErrorText: array [0..LASTERRORTEXTLENGTH] of char;
function GetLastErrorText: PChar;
begin
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
nil, GetLastError, 0, LastErrorText, LASTERRORTEXTLENGTH, nil );
Result := LastErrorText;
end;
procedure TNotificationThread.Execute;
var
h: THandle;
nf: Longint;
wst: LongBool;
begin
nf := 0;
if (nfFileName in Owner.Filter) then
nf := FILE_NOTIFY_CHANGE_FILE_NAME;
if (nfDirName in Owner.Filter) then
nf := nf or FILE_NOTIFY_CHANGE_DIR_NAME;
if (nfAttributes in Owner.Filter) then
nf := nf or FILE_NOTIFY_CHANGE_ATTRIBUTES;
if (nfSize in Owner.Filter) then
nf := nf or FILE_NOTIFY_CHANGE_SIZE;
if (nfLastWrite in Owner.Filter) then
nf := nf or FILE_NOTIFY_CHANGE_LAST_WRITE;
if (nfSecurity in Owner.Filter) then
nf := nf or FILE_NOTIFY_CHANGE_SECURITY;
// yeahh, this one is stupid but Win98 malfunctions in any other value than 0 or 1
if Owner.FWatchSubTree then
wst := Longbool(1)
else
wst := Longbool(0);
h := FindFirstChangeNotification( Pointer(Owner.Path), wst, nf );
if (h = INVALID_HANDLE_VALUE) then
raise EDirNotificationError.Create( GetLastErrorText );
repeat
if (WaitForSingleObject( h, 1000 ) = WAIT_OBJECT_0) then
begin
Synchronize(DoChange);
if not FindNextChangeNotification( h ) then
raise EDirNotificationError.Create( GetLastErrorText );
end;
until Terminated;
end;
procedure TNotificationThread.DoChange;
begin
Owner.Change;
end;
constructor TDirNotify.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEnabled := True;
FFilter := [nfFileName];
end;
destructor TDirNotify.Destroy;
begin
FNotificationThread.Free;
inherited Destroy;
end;
procedure TDirNotify.Loaded;
begin
inherited;
RecreateThread;
end;
procedure TDirNotify.SetEnabled(Value: Boolean);
begin
if Value <> FEnabled then
begin
FEnabled := Value;
RecreateThread;
end;
end;
procedure TDirNotify.SetPath( Value: String );
begin
if Value <> FPath then
begin
FPath := Value;
RecreateThread;
end;
end;
procedure TDirNotify.SetWatchSubTree( Value: Boolean );
begin
if Value <> FWatchSubTree then
begin
FWatchSubTree := Value;
RecreateThread;
end;
end;
procedure TDirNotify.SetFilter( Value: TNotifyFilters );
begin
if Value <> FFilter then
begin
FFilter := Value;
RecreateThread;
end;
end;
procedure TDirNotify.SetOnChange(Value: TNotifyEvent);
begin
FOnChange := Value;
end;
procedure TDirNotify.Change;
begin
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TDirNotify.RecreateThread;
begin
// destroy thread
FNotificationThread.Free;
FNotificationThread := nil;
if FEnabled and not(csDesigning in ComponentState)
and not(csLoading in ComponentState) and (FPath <> '') then
begin
// create thread
FNotificationThread := TNotificationThread.Create(True);
FNotificationThread.Owner := self;
FNotificationThread.Resume;
end;
end;
procedure Register;
begin
RegisterComponents('System', [TDirNotify]);
end;
end.