首页 > 代码库 > 使用完成例程监控文件目录的例子
使用完成例程监控文件目录的例子
由于项目需要实现了一个文件监控服务,期间研究过使用完成例程的方式来监控文件目录。
下面简单的BCB6命令行实现版本。(参考来源 http://bbs.csdn.net/topics/340172813 )
下次补充一个完成端口的版本。
1 //--------------------------------------------------------------------------- 2 // 使用完成例程监控当前文件夹 3 //------------------------------------------------------------------------------ 4 5 6 7 8 #include <vcl.h> 9 #pragma hdrstop 10 #include <iostream> 11 using namespace std; 12 13 14 //--------------------------------------------------------------------------- 15 16 #pragma argsused 17 18 19 HANDLE hThreadHandle = NULL ; 20 HANDLE hMonitorDirHandle = NULL; 21 HANDLE hMonitorEventHandle = NULL; 22 23 //这个回调函数,是完成例程的核心 24 //在IO 完成的时候会触发。 25 //然后这个回调函数去设置overlapped->hEvent信号量 26 //使线程能不被阻塞。 27 void CALLBACK FileIOCompletionRoutine( DWORD dwErrorCode, 28 DWORD dwNumberOfBytesTransfered, 29 LPOVERLAPPED lpOverlapped) 30 { 31 if(dwErrorCode) 32 { 33 printf("Error Code:%d\r\n",dwErrorCode); 34 } 35 //设置信号量,多线程会得到通知 36 SetEvent(lpOverlapped->hEvent); 37 } 38 39 DWORD WINAPI MonitorThread( LPVOID ) 40 { 41 OVERLAPPED overlapped={0}; 42 DWORD ByteReturn = 0; 43 DWORD BufferLen=10*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH*sizeof(TCHAR)); 44 FILE_NOTIFY_INFORMATION* Buffer= 45 (FILE_NOTIFY_INFORMATION*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,BufferLen); 46 47 while(true) 48 { 49 //简单起见只监控了 修改文件和文件目录 50 if(ReadDirectoryChangesW(hMonitorDirHandle,Buffer,BufferLen,TRUE, 51 FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME, 52 &ByteReturn,&overlapped,FileIOCompletionRoutine)) 53 { 54 DWORD dwResult; 55 //这个信号一开始没信号的,直到完成例程回调被调用(FileIOCompletionRoutine) 56 dwResult=WaitForSingleObjectEx(hMonitorEventHandle,INFINITE,TRUE); 57 if(dwResult==WAIT_IO_COMPLETION ) 58 { 59 FILE_NOTIFY_INFORMATION* notify = Buffer; 60 61 AnsiString fileName = 62 WideCharLenToString( 63 notify->FileName,notify->FileNameLength/2); 64 do 65 { 66 bool blNormal = true; 67 switch(notify->Action) 68 { 69 case FILE_ACTION_ADDED: 70 { 71 cout<<"增加了文件"<<fileName.c_str()<<endl; 72 } 73 break; 74 case FILE_ACTION_REMOVED: 75 { 76 cout<<"删除了文件"<<fileName.c_str()<<endl; 77 } 78 break; 79 case FILE_ACTION_MODIFIED: 80 { 81 cout<<"修改了文件"<<fileName.c_str()<<endl; 82 } 83 break; 84 case FILE_ACTION_RENAMED_OLD_NAME: 85 { 86 cout<<"被重名的文件"<<fileName.c_str()<<endl; 87 } 88 break; 89 case FILE_ACTION_RENAMED_NEW_NAME: 90 { 91 cout<<"新命名的文件"<<fileName.c_str()<<endl; 92 } 93 break; 94 default: //有可能已经溢出了! 95 blNormal = false; 96 break; 97 } 98 99 if(!blNormal)100 {101 break;102 }103 //将指针偏移offset个字节104 notify = notify + notify->NextEntryOffset;105 }106 while(notify->NextEntryOffset>0);107 }108 //重新设置信号量,继续阻塞109 ResetEvent(hMonitorEventHandle);110 }111 else112 {113 cout<<"缓冲溢出!"<<SysErrorMessage(GetLastError()).c_str()<<endl;114 break;115 }116 }117 HeapFree(GetProcessHeap(),0,Buffer);118 return 0;119 }120 121 int main(int argc, char* argv[])122 {123 AnsiString mointorDir = ExtractFileDir(Application->ExeName);124 125 hMonitorDirHandle=CreateFile(mointorDir.c_str(),126 FILE_LIST_DIRECTORY, //见MSDN ReadDirectoryChangesW 函数说明127 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,128 NULL,129 OPEN_EXISTING,130 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,//FILE_FLAG_OVERLAPPED表示异步模式,当异步的IO 完成的时,会填充OVERLAPPED结构131 NULL);132 133 if(hMonitorDirHandle == INVALID_HANDLE_VALUE)134 {135 cout<<"打开监控文件夹失败!"<< SysErrorMessage(GetLastError()).c_str() <<endl;136 CloseHandle(hMonitorDirHandle);137 return 0;138 }139 140 hMonitorEventHandle = CreateEvent(NULL,TRUE,FALSE,NULL);141 142 DWORD threadId = 0;143 hThreadHandle = CreateThread(NULL,0,MonitorThread,NULL,0,&threadId);144 145 146 cout<<"开始监控本程序所在的文件夹..."<<endl;147 int i=0;148 cin>>i;149 150 CloseHandle(hThreadHandle);151 CloseHandle(hMonitorDirHandle);152 CloseHandle(hMonitorEventHandle);153 return 0;154 }155 //---------------------------------------------------------------------------
使用完成例程监控文件目录的例子
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。