分类: C/C++
2008-03-14 14:12:04
// 名称: FileSystemWatcher // 功能: 监测指定目录中的文件/目录的改变 // 环境要求: Requires Windows NT 3.51 SP3 or later, and Unsupported Windows 95/98. // 版权申明: 可任意拷贝、修改、发布 // 作者: 周星星 // 日期: 2003-08-07 // 说明: 未做测试 // VCKBASE.COM #define _WIN32_WINNT 0x0500 #include以下是测试代码#include #include enum ACTION { ADDED=1, REMOVED=2, MODIFIED=3, RENAMED=4 }; class FileSystemWatcher { public: typedef void (__stdcall *LPDEALFUNCTION)( ACTION act, std::string filename1, std::string filename2 ); bool Run( std::string path, LPDEALFUNCTION dealfun ) { WatchedDir = path; DealFun = dealfun; DWORD ThreadId; hThread=CreateThread( NULL,0,Routine,this,0,&ThreadId ); return NULL!=hThread; } void Close() { if( NULL != hThread ) { TerminateThread( hThread, 0 ); hThread = NULL; } if( INVALID_HANDLE_VALUE != hDir ) { CloseHandle( hDir ); hDir = INVALID_HANDLE_VALUE; } } FileSystemWatcher() : DealFun(NULL), hThread(NULL), hDir(INVALID_HANDLE_VALUE) { } ~FileSystemWatcher() { Close(); } private: std::string WatchedDir; LPDEALFUNCTION DealFun; HANDLE hThread; HANDLE hDir; private: FileSystemWatcher( const FileSystemWatcher& ); FileSystemWatcher operator=( const FileSystemWatcher ); private: static DWORD WINAPI Routine( LPVOID lParam ) { FileSystemWatcher* obj = (FileSystemWatcher*)lParam; obj->hDir = CreateFile( obj->WatchedDir.c_str(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); if( INVALID_HANDLE_VALUE == obj->hDir ) return false; char buf[ 2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ]; FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf; DWORD BytesReturned; while(true) { if( ReadDirectoryChangesW( obj->hDir, pNotify, sizeof(buf), true, FILE_NOTIFY_CHANGE_FILE_NAME| FILE_NOTIFY_CHANGE_DIR_NAME| FILE_NOTIFY_CHANGE_ATTRIBUTES| FILE_NOTIFY_CHANGE_SIZE| FILE_NOTIFY_CHANGE_LAST_WRITE| FILE_NOTIFY_CHANGE_LAST_ACCESS| FILE_NOTIFY_CHANGE_CREATION| FILE_NOTIFY_CHANGE_SECURITY, &BytesReturned, NULL, NULL ) ) { char tmp[MAX_PATH], str1[MAX_PATH], str2[MAX_PATH]; memset( tmp, 0, sizeof(tmp) ); WideCharToMultiByte( CP_ACP,0,pNotify->FileName,pNotify->FileNameLength/2,tmp,99,NULL,NULL ); strcpy( str1, tmp ); if( 0 != pNotify->NextEntryOffset ) { PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pNotify+pNotify->NextEntryOffset); memset( tmp, 0, sizeof(tmp) ); WideCharToMultiByte( CP_ACP,0,p->FileName,p->FileNameLength/2,tmp,99,NULL,NULL ); strcpy( str2, tmp ); } obj->DealFun( (ACTION)pNotify->Action, str1, str2 ); } else { break; } } return 0; } };
#include#include using namespace std; void __stdcall MyDeal( ACTION act, std::string filename1, std::string filename2 ) { switch( act ) { case ADDED: cout << "Added - " << filename1 << endl; break; case REMOVED: cout << "Removed - " << filename1 << endl; break; case MODIFIED: cout << "Modified - " << filename1 << endl; break; case RENAMED: cout << "Rename - " << filename1 << " " << filename2 << endl; break; } } void main() { FileSystemWatcher a; a.Run( "D:\\", MyDeal ); cout << "Watch D:\\" << endl; cout << "Press to quit." << endl; while(getch()!='q'); a.Close(); }
以上代码在 Win2K + VC++6.0 中调试通过,写在同一个文件中是为了调试方便,正式使用时最好能拆分成h文件和cpp文件; 我本想既支持Ansi编码又支持Unicode,但后来心情浮躁,就懒得写了,甚至也没有做足够的测试,所以这段代码写得是很差的,但我实在不想再写了,只想睡觉,所以贴出来抛砖引玉,希望诸位能将修正后的代码贴上来。