使用完成例程监控文件目录的例子

由于项目需要实现了一个文件监控服务,期间研究过使用完成例程的方式来监控文件目录。

下面简单的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
",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         else
112         {
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 //---------------------------------------------------------------------------
原文地址:https://www.cnblogs.com/songr/p/4168320.html