如何用c++builder编程实现时实监视哪些文件被访问过?
请高手帮忙 ,最好能带说明原理的例程,谢谢!!! 问题点数:20、回复次数:10Top
1 楼luhongjun(过江项羽)回复于 2001-05-23 10:58:00 得分 5
看一看
http://community.borland.com/article/0,1410,21743,00.html
你不会失望的。Top
2 楼rh(花覆茅檐)回复于 2001-05-23 11:31:00 得分 0
英文啊!Top
3 楼rh(花覆茅檐)回复于 2001-05-23 11:32:00 得分 15
The concept behind directory monitoring is fairly simple. As I said above, this can be done using the function FindFirstChangeNotification. That said and done, how do we go about actually using the thing? First lets look at the prototype, as given by Microsoft:
HANDLE FindFirstChangeNotification(
LPCTSTR lpPathName, // directory name
BOOL bWatchSubtree, // monitoring option
DWORD dwNotifyFilter // filter conditions
);
Parameters
lpPathName: the path of the directory to monitor
bWatchSubtree: whether or not to recursively monitor subdirectories
dwNotifyFilter: flags to control monitoring conditions
The options available for dwNotifyFilter are as follows:
Value Meaning
FILE_NOTIFY_CHANGE_FILE_NAME Any file name change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file name.
FILE_NOTIFY_CHANGE_DIR_NAME Any directory-name change in the watched directory or subtree causes a change notification wait operation to return. Changes include creating or deleting a directory.
FILE_NOTIFY_CHANGE_ATTRIBUTES Any attribute change in the watched directory or subtree causes a change notification wait operation to return.
FILE_NOTIFY_CHANGE_SIZE Any file-size change in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change in file size only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.
FILE_NOTIFY_CHANGE_LAST_WRITE Any change to the last write-time of files in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change to the last write-time only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.
FILE_NOTIFY_CHANGE_SECURITY Any security-descriptor change in the watched directory or subtree causes a change notification wait operation to return.
The return value of this function is a windows HANDLE type. It gives us a Windows event object, which is an object that can be set to have a signalled state. Using this event handle, we can call the WaitForSingleObject or WaitForMultipleObjects functions to wait until it is signalled (the monitored directory has changed in some way). Once the event becomes signalled (i.e. a change was detected), it is necessary to call the FindNextChangeNotification. function to reset it. When you are finished, you must free the object with FindCloseChangeNotification
One way to utilize this function in a component is to put it within a thread with a loop that calls FindFirstChangeNotification, WaitForSingleObject, FindNextChangeNotification, and FindCloseChangeNotification. Every time the event object becomes signalled, we can call a function in the ListBox component that will notify it of change.
Implementation
In implementing a directory monitoring and auto-updating file ListBox, there are a couple of things to keep in mind: how to monitor the directory without locking your application, and how to notify the control.One relatively simple way of accomplishing this is to create a thread that monitors the directory and calls back to the ListBox component when there is a change. In the following source, both code for a ListBox and for the monitoring thread are provided.
Here is the code for the component:
ActiveListBox.h
//---------------------------------------------------------------------------
#ifndef ActiveListBoxH
#define ActiveListBoxH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <StdCtrls.hpp>
//---------------------------------------------------------------------------
//Here we combine the flags into one easy-to-use dword
const unsigned long dwFlags = FILE_NOTIFY_CHANGE_FILE_NAME|
FILE_NOTIFY_CHANGE_DIR_NAME|
FILE_NOTIFY_CHANGE_ATTRIBUTES|
FILE_NOTIFY_CHANGE_SIZE|
FILE_NOTIFY_CHANGE_LAST_WRITE;
class TActiveListBox;
class TDirectoryThread : public TThread
{
private:
HANDLE hNotify; //Event object handle
TActiveListBox *control; //ListBox back pointer (to notify it)
String path; //Path to monitor
void __fastcall Update();
void __fastcall ThreadFinish(TObject *Sender);
protected:
void __fastcall Execute();
public:
__fastcall TDirectoryThread(TActiveListBox *ctrl);
void __fastcall SetMonitorPath(String path);
};
//---------------------------------------------------------------------------
class PACKAGE TActiveListBox : public TListBox
{
private:
bool path_set;
TNotifyEvent FOnChangeFile; //Change event
TDirectoryThread *thrd; //Monitoring thread
AnsiString FPath;
void __fastcall SetPath(String path);
void __fastcall PopulateFileList();
protected:
public:
__fastcall TActiveListBox(TComponent* Owner);
__fastcall ~TActiveListBox();
void __fastcall UpdateNotify();
void __fastcall Restart();
__published:
__property AnsiString MonitorPath = {read=FPath,write=SetPath};
__property TNotifyEvent OnDirectoryChange = {read=FOnChangeFile,write=FOnChangeFile};
};
//---------------------------------------------------------------------------
#endif
ActiveListBox.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "ActiveListBox.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
static inline void ValidCtrCheck(TActiveListBox *)
{
new TActiveListBox(NULL);
}
//---------------------------------------------------------------------------
__fastcall TActiveListBox::TActiveListBox(TComponent* Owner)
: TListBox(Owner)
{
path_set=false; //boolean to check if path has been set
FPath="";
FOnChangeFile=NULL;
thrd = new TDirectoryThread(this); //create thread
}
//---------------------------------------------------------------------------
__fastcall TActiveListBox::~TActiveListBox()
{
thrd->Terminate();
}
//---------------------------------------------------------------------------
void __fastcall TActiveListBox::SetPath(String path)
{
FPath = path;
PopulateFileList();
thrd->SetMonitorPath(FPath);
if (!path_set) //if the path hasn't been set yet...
{
path_set=true;
thrd->Resume(); //start the thread
}
}
//---------------------------------------------------------------------------
void __fastcall TActiveListBox::UpdateNotify() //notify the listbox of changes
{
PopulateFileList();
if (FOnChangeFile)
FOnChangeFile(this);
}
//---------------------------------------------------------------------------
void __fastcall TActiveListBox::PopulateFileList() //fill list box w/ files
{
TSearchRec sr;
Items->Clear();
if (FPath == "") return;
FindFirst(FPath+"*.*",faAnyFile,sr);
do {
Items->Add(sr.Name);
} while (!FindNext(sr));
FindClose(sr);
}
//---------------------------------------------------------------------------
void __fastcall TActiveListBox::Restart()
{
path_set=false;
thrd = new TDirectoryThread(this);
}
//---------------------------------------------------------------------------
namespace Activelistbox
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TActiveListBox)};
RegisterComponents("Samples", classes, 0);
}
}
//---------------------------------------------------------------------------
__fastcall TDirectoryThread::TDirectoryThread(TActiveListBox *ctrl)
: TThread(true)
{
control = ctrl;
path = "";
FreeOnTerminate = true;
OnTerminate = ThreadFinish;
hNotify = INVALID_HANDLE_VALUE;
}
//---------------------------------------------------------------------------
void __fastcall TDirectoryThread::Execute()
{
if (path.IsEmpty() || (hNotify == INVALID_HANDLE_VALUE))
{
control->Restart();
throw Exception("couldn't start");
}
bool to=true; //time-out check
//while we're still going...
while (!Terminated && (hNotify != INVALID_HANDLE_VALUE))
{
//while we're still timed out...
while (to && !Suspended && !Terminated)
{
unsigned long stat = WaitForSingleObject(hNotify,2000);
//our call to WaitForSingleObject has a 2 second timeout to avoid thread-lock
if (stat == WAIT_OBJECT_0) //if it got signalled
{
to=true;
Synchronize(Update()); //update list box
//use Synchronize to keep it thread-safe
if (!FindNextChangeNotification(hNotify)) //renew the handle
{
to=false;
break;
}
}
else if (stat == WAIT_TIMEOUT) //just keep going
to=true;
else {
to=false;
break;
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TDirectoryThread::SetMonitorPath(String Path)
{
if (path != Path)
{
path = Path;
if (hNotify != INVALID_HANDLE_VALUE) //close our old handle
FindCloseChangeNotification(hNotify);
hNotify = FindFirstChangeNotification(path.c_str(),false,dwFlags);
//get the handle to the event object
if (hNotify == INVALID_HANDLE_VALUE)
throw Exception("couldn't make handle");
}
}
//---------------------------------------------------------------------------
void __fastcall TDirectoryThread::ThreadFinish(TObject *Sender)
{
FindCloseChangeNotification(hNotify); //cleanup
}
//---------------------------------------------------------------------------
void __fastcall TDirectoryThread::Update()
{
control->UpdateNotify();
}
Top
4 楼Adayuer(饭碗饭碗饭碗你在哪里?)回复于 2001-05-26 09:50:00 得分 0
谢谢Top
5 楼Adayuer(饭碗饭碗饭碗你在哪里?)回复于 2001-05-31 08:33:00 得分 0
6 楼Adayuer(饭碗饭碗饭碗你在哪里?)回复于 2001-05-31 08:33:00 得分 0
7 楼xrbeck(ALEK)回复于 2001-05-31 08:36:00 得分 0
妈呀。。。跑路Top
8 楼TR@SOE()回复于 2001-05-31 09:01:00 得分 0
可以使用控件。Orpheus里的SysTools中封装了一个。Top
9 楼Adayuer(饭碗饭碗饭碗你在哪里?)回复于 2001-05-31 17:25:00 得分 0
在哪能得到这个控件,免费的吗?Top




