分类: C/C++
2008-03-14 14:11:14
测试VC知识库中周星星所写的《目录监测》一文所提供的程序,发现有一些不够完善的地方,遂写出与大家共同探讨。
问题:
原程序中在处理多个文件拷贝和山删除时不能完全显示,如对200个文件进行拷贝:
copy temp\*.txt
仅能监控到3个文件变化,目前发现拷贝时对同一个文件有5个 FILE_ACTION_ADDED 显示
( 测试环境: Microsoft Windows 2000 [Version 5.00.2195] )
一、对FileSystemWatcher.h 的改进:
#define _WIN32_WINNT 0x0500 #include二、对FileSystemWatcher.cpp 的改进:#include #include void SendOutNotify(PFILE_NOTIFY_INFORMATION f_pNotify); #define DeFileWaterBuffer (1000* (sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ) 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 ); hThread=CreateThread( NULL,0,RoutineTest,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 ); */ //hcs change obj->hDir = CreateFile( obj->WatchedDir.c_str(), // pointer to the file name FILE_LIST_DIRECTORY, // access (read/write) mode FILE_SHARE_READ|FILE_SHARE_DELETE, // share mode NULL, // security descriptor OPEN_EXISTING, // how to create FILE_FLAG_BACKUP_SEMANTICS, // file attributes NULL // file with attributes to copy ); if( INVALID_HANDLE_VALUE == obj->hDir ) return false; char buf[ 50*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ]; FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf; DWORD BytesReturned; while(true) { memset(buf,0,sizeof(buf)); 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 ); */ SendOutNotify(pNotify); } else { break; } } return 0; } static DWORD WINAPI RoutineTest( LPVOID lParam ) { FileSystemWatcher* obj = (FileSystemWatcher*)lParam; //hcs change obj->hDir = CreateFile( obj->WatchedDir.c_str(), // pointer to the file name FILE_LIST_DIRECTORY, // access (read/write) mode FILE_SHARE_READ|FILE_SHARE_DELETE, // share mode NULL, // security descriptor OPEN_EXISTING, // how to create FILE_FLAG_BACKUP_SEMANTICS, // file attributes NULL // file with attributes to copy ); if( INVALID_HANDLE_VALUE == obj->hDir ) return false; char *pcBufferNs=new char[DeFileWaterBuffer]; FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)pcBufferNs; DWORD BytesReturned; while(true) { memset(pcBufferNs,0,DeFileWaterBuffer); BytesReturned=0; if( ReadDirectoryChangesW( obj->hDir, pNotify, DeFileWaterBuffer, 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 ); */ if(BytesReturned> 0) { SendOutNotify(pNotify); } else { //AfxMessageBox("Buffer is small"); MessageBox(0,"Buffer is small","error",MB_OK); } } else { break; } } delete [] pcBufferNs; return 0; } };
#include "stdafx.h" #include#include #include "FileSystemWatcher.h" using namespace std; static int g_nChangeTimes; void __stdcall MyDeal( ACTION act, std::string filename1, std::string filename2 ) { g_nChangeTimes++; /* 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; a.Run( "C:\\", MyDeal ); cout << "Watch C:\\" << endl; cout << "Press to quit." << endl; while(getch()!=''q''); a.Close(); } //hcs add use for test file change void SendOutNotify(PFILE_NOTIFY_INFORMATION f_pNotify) { PFILE_NOTIFY_INFORMATION pNextNotify=f_pNotify ; char pcfilename[MAX_PATH]; for(int i=0;i<5000;i++) { g_nChangeTimes++; memset(pcfilename , 0, MAX_PATH ); WideCharToMultiByte( CP_ACP,0,pNextNotify->FileName,pNextNotify->FileNameLength/2,pcfilename,MAX_PATH,NULL,NULL ); //*(pcfilename+f_pNotify->FileNameLength)=0; switch( f_pNotify->Action ) { case FILE_ACTION_ADDED: cout << "Added - " << pcfilename << endl; break; case FILE_ACTION_REMOVED: cout << "Removed - " << pcfilename << endl; break; case FILE_ACTION_MODIFIED: cout << "Modified - " << pcfilename << endl; break; case FILE_ACTION_RENAMED_OLD_NAME: cout << "Rename - " << pcfilename << " " << "filename2" << endl; break; case FILE_ACTION_RENAMED_NEW_NAME: cout << "RenameNew - " << pcfilename << " " << "filename2" << endl; break; } cout << "Message Times is" << i << " File Len is "<< g_nChangeTimes << endl;; //pNextNotify->FileNameLength << endl; if(pNextNotify->NextEntryOffset) { pNextNotify=(PFILE_NOTIFY_INFORMATION)((char*)pNextNotify+pNextNotify->NextEntryOffset); } else { break; } } return; } (全文完)