转载:http://www.cnblogs.com/doublesnke/archive/2011/08/16/2141374.html
VC++实施文件监控:实例和详解
相关帮助: http://hi.baidu.com/jiahaosoft/blog/item/b441d1218eebece0d6cae274.html
我这里只介绍采用ReadDirectoryChangesW对文件目录实施监控
关键代码
CfgdsgDlg * dlg = (CfgdsgDlg*)lparam; HANDLE hDir; char notify[1024]; DWORD cbBytes,i; char AnsiChar[3]; wchar_t UnicodeChar[2]; CString path; FILE_NOTIFY_INFORMATION *pnotify=(FILE_NOTIFY_INFORMATION *)notify; FILE_NOTIFY_INFORMATION *tmp; GetCurrentDirectory(MAX_PATH,path.GetBuffer(MAX_PATH+1)); hDir = CreateFile( path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); if (hDir == INVALID_HANDLE_VALUE) { dlg->m_edit.ReplaceSel( "hDir:INVALID_HANDLE_VALUE
" ); return 0; } while (TRUE) { if (ReadDirectoryChangesW(hDir, ¬ify, sizeof (notify), FALSE, FILE_NOTIFY_CHANGE_FILE_NAME| FILE_NOTIFY_CHANGE_LAST_WRITE, &cbBytes, NULL, NULL)) { tmp = pnotify; switch (tmp->Action) { case FILE_ACTION_ADDED: dlg->m_edit.ReplaceSel( "Directory/File added (添加文件)-
" ); break ; case FILE_ACTION_REMOVED: dlg->m_edit.ReplaceSel( "Directory/File removed (删除文件)-
" ); break ; case FILE_ACTION_MODIFIED: dlg->m_edit.ReplaceSel( "Directory/File modified (修改文件内容)-
" ); break ; case FILE_ACTION_RENAMED_OLD_NAME: dlg->m_edit.ReplaceSel( "Directory/File old name (修改文件名字)-
" ); break ; case FILE_ACTION_RENAMED_NEW_NAME: dlg->m_edit.ReplaceSel( "Directory/File new name -
" ); break ; default : break ; } } } |
FILE_NOTIFY_INFORMATION //可以确定是那个文件进行的修改
typedef struct _FILE_NOTIFY_INFORMATION {
DWORD NextEntryOffset;
DWORD Action;//动作
DWORD FileNameLength;//文件名字的长度
WCHAR FileName[1];//文件名字
} FILE_NOTIFY_INFORMATION,
*PFILE_NOTIFY_INFORMATION;
ReadDirectoryChangesW 返回类型(见MSDN)
Value | Meaning |
---|---|
FILE_ACTION_ADDED |
The file was added to the directory. |
FILE_ACTION_REMOVED |
The file was removed from the directory. |
FILE_ACTION_MODIFIED |
The file was modified. This can be a change in the time stamp or attributes. |
FILE_ACTION_RENAMED_OLD_NAME |
The file was renamed and this is the old name. |
FILE_ACTION_RENAMED_NEW_NAME |
The file was renamed and this is the new name. |
效果如下:
不足的地方:
只能检测到指定目录和下一级目录,超过目录级数,该函数检测不到。
2. 转载:http://blog.csdn.net/visualeleven/article/details/7562014
1 // .h文件 2 #pragma once 3 4 typedef void (*PFN_NotifyAction)(DWORD dwAction, LPWSTR szFile, DWORD dwLength); 5 6 class CDirectoryWatch 7 { 8 public: 9 CDirectoryWatch(void); 10 virtual ~CDirectoryWatch(void); 11 12 public: 13 BOOL StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction); 14 BOOL StopDirectoryWatch(void); 15 16 private: 17 static UINT __cdecl ThreadProc(LPVOID lParam); 18 static UINT __cdecl DirectoryWatch(LPVOID lParam); 19 20 private: 21 HANDLE m_hFile; 22 CWinThread* m_pThread; 23 TCHAR m_szDirectory[MAX_PATH]; 24 };
1 // .cpp文件 2 #include "StdAfx.h" 3 #include "DirectoryWatch.h" 4 #include <strsafe.h> 5 6 typedef enum 7 { 8 MSG_STARTWATCH = (WM_USER + 0x11), 9 MSG_STOPWATCH, 10 MSG_EXITTHREAD 11 }; 12 13 #define MAX_BUFFER_SIZE (1024) 14 15 typedef struct _tagWATCHPARAMETERS 16 { 17 _tagWATCHPARAMETERS() 18 { 19 hFile = INVALID_HANDLE_VALUE; 20 hEvent = NULL; 21 memset(&ol, 0, sizeof(OVERLAPPED)); 22 pBuffer = NULL; 23 dwBufferSize = 0; 24 bExit = FALSE; 25 pFn_NotifyAction = NULL; 26 } 27 HANDLE hFile; 28 HANDLE hEvent; 29 OVERLAPPED ol; 30 BYTE* pBuffer; 31 DWORD dwBufferSize; 32 BOOL bExit; 33 PFN_NotifyAction pFn_NotifyAction; 34 }WATCH_PARAMETERS, *PWATCH_PARAMETERS; 35 36 CDirectoryWatch::CDirectoryWatch() : m_hFile(INVALID_HANDLE_VALUE), m_pThread(NULL) 37 { 38 memset(m_szDirectory, 0, sizeof(m_szDirectory)); 39 40 m_pThread = AfxBeginThread(ThreadProc, NULL, 0, CREATE_SUSPENDED, 0, NULL); 41 if(NULL == m_pThread) 42 { 43 TRACE("Error Code : %d ", GetLastError()); 44 return ; 45 } 46 m_pThread->m_bAutoDelete = FALSE; 47 m_pThread->ResumeThread(); 48 } 49 50 51 CDirectoryWatch::~CDirectoryWatch() 52 { 53 if(INVALID_HANDLE_VALUE != m_hFile) 54 { 55 CloseHandle(m_hFile); 56 m_hFile = INVALID_HANDLE_VALUE; 57 } 58 59 if((NULL != m_pThread) && (NULL != m_pThread->m_hThread)) 60 { 61 62 m_pThread->PostThreadMessage(MSG_EXITTHREAD, 0, 0); 63 WaitForSingleObject(m_pThread->m_hThread, INFINITE); 64 delete m_pThread; 65 m_pThread = NULL; 66 } 67 } 68 69 BOOL CDirectoryWatch::StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction) 70 { 71 if(NULL == m_pThread) 72 { 73 return FALSE; 74 } 75 76 if(NULL == lpszDirectory) 77 { 78 return FALSE; 79 } 80 81 if(NULL == pFn_NotifyAction) 82 { 83 return FALSE; 84 } 85 86 if(!PathFileExists(lpszDirectory)) 87 { 88 TRACE("Error Code : %d ", GetLastError()); 89 return FALSE; 90 } 91 92 if(!PathIsDirectory(lpszDirectory)) 93 { 94 TRACE("Error Code : %d ", GetLastError()); 95 return FALSE; 96 } 97 98 if(0 == _tcslen(m_szDirectory)) 99 { 100 StringCchPrintf(m_szDirectory, _countof(m_szDirectory), _T("%s"), lpszDirectory); 101 } 102 else if(CSTR_EQUAL != CompareStringOrdinal(m_szDirectory, -1, lpszDirectory, -1, TRUE)) 103 { 104 TRACE("Not Change Directory. "); 105 return FALSE; 106 } 107 108 if(INVALID_HANDLE_VALUE == m_hFile) 109 { 110 m_hFile = CreateFile(lpszDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 111 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); 112 if(INVALID_HANDLE_VALUE == m_hFile) 113 { 114 TRACE("Error Code : %d ", GetLastError()); 115 return FALSE; 116 } 117 } 118 119 return m_pThread->PostThreadMessage(MSG_STARTWATCH, (WPARAM)m_hFile, (LPARAM)pFn_NotifyAction); 120 } 121 122 BOOL CDirectoryWatch::StopDirectoryWatch() 123 { 124 if(NULL != m_pThread) 125 { 126 return m_pThread->PostThreadMessage(MSG_STOPWATCH, 0, 0); 127 } 128 129 return FALSE; 130 } 131 132 UINT __cdecl CDirectoryWatch::DirectoryWatch(LPVOID lParam) 133 { 134 WATCH_PARAMETERS* pParam = (WATCH_PARAMETERS*)lParam; 135 if(NULL == pParam) 136 { 137 return 0; 138 } 139 HANDLE& hFile = pParam->hFile; 140 BYTE* pBuffer = pParam->pBuffer; 141 DWORD dwBufferSize = pParam->dwBufferSize; 142 OVERLAPPED& ol = pParam->ol; 143 HANDLE& hEvent = pParam->hEvent; 144 BOOL& bExit = pParam->bExit; 145 PFN_NotifyAction pFn_NotifyAction = pParam->pFn_NotifyAction; 146 DWORD dwBytesReturn = 0; 147 DWORD dwRet = WAIT_FAILED; 148 DWORD dwOffSet = 0; 149 TCHAR szFile[MAX_PATH] = {0}; 150 while(TRUE) 151 { 152 if(WAIT_OBJECT_0 != WaitForSingleObject(hEvent, INFINITE)) 153 { 154 TRACE("Error Code : %d ", GetLastError()); 155 break; 156 } 157 158 if(bExit) 159 { 160 break; 161 } 162 163 if(!ReadDirectoryChangesW(hFile, pBuffer, dwBufferSize, TRUE, 164 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES 165 | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS 166 | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, &dwBytesReturn, &ol, NULL)) 167 { 168 TRACE("Error Code : %d ", GetLastError()); 169 break; 170 } 171 if(!GetOverlappedResult(hFile, &ol, &dwBytesReturn, TRUE)) 172 { 173 TRACE("Error Code : %d ", GetLastError()); 174 break; 175 } 176 FILE_NOTIFY_INFORMATION* pFileNotify = (FILE_NOTIFY_INFORMATION*)pBuffer; 177 178 do 179 { 180 if(pFn_NotifyAction && (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0))) 181 { 182 pFn_NotifyAction(pFileNotify->Action, pFileNotify->FileName, (pFileNotify->FileNameLength) / sizeof(WCHAR)); 183 } 184 185 dwOffSet = pFileNotify->NextEntryOffset; 186 pFileNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pFileNotify + dwOffSet); 187 } while (dwOffSet); 188 } 189 TRACE0("DirectoryWatch Thread Exit ... "); 190 return 0; 191 } 192 193 UINT __cdecl CDirectoryWatch::ThreadProc(LPVOID lParam) 194 { 195 WATCH_PARAMETERS* pParam = new WATCH_PARAMETERS; 196 197 if(NULL == pParam) 198 { 199 goto __CLEANUP__; 200 } 201 202 BYTE* pBuffer = new BYTE[MAX_BUFFER_SIZE]; 203 if(NULL == pBuffer) 204 { 205 goto __CLEANUP__; 206 } 207 memset(pBuffer, 0, MAX_BUFFER_SIZE); 208 pParam->pBuffer = pBuffer; 209 pParam->dwBufferSize = MAX_BUFFER_SIZE; 210 HANDLE hWatchEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 211 if(NULL == hWatchEvent) 212 { 213 goto __CLEANUP__; 214 } 215 pParam->ol.hEvent = hWatchEvent; 216 CWinThread* pThread = NULL; 217 HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 218 if(NULL == hEvent) 219 { 220 goto __CLEANUP__; 221 } 222 pParam->hEvent = hEvent; 223 MSG msg; 224 while(GetMessage(&msg, NULL, 0, 0)) 225 { 226 switch(msg.message) 227 { 228 case MSG_STARTWATCH: 229 { 230 HANDLE hFile = (HANDLE)(msg.wParam); 231 PFN_NotifyAction pFn_NotifyAction = (PFN_NotifyAction)(msg.lParam); 232 if((INVALID_HANDLE_VALUE == hFile) && (NULL == pFn_NotifyAction)) 233 { 234 break; 235 } 236 if(NULL == pThread) 237 { 238 pParam->hFile = hFile; 239 pParam->pFn_NotifyAction = pFn_NotifyAction; 240 pThread = AfxBeginThread(DirectoryWatch, (LPVOID)pParam, 0, CREATE_SUSPENDED, NULL); 241 if(NULL == pThread) 242 { 243 goto __CLEANUP__; 244 } 245 pThread->m_bAutoDelete = FALSE; 246 pThread->ResumeThread(); 247 } 248 SetEvent(hEvent); 249 } 250 break; 251 252 case MSG_STOPWATCH: 253 { 254 ResetEvent(hEvent); 255 } 256 break; 257 258 case MSG_EXITTHREAD: 259 { 260 SetEvent(hEvent); 261 pParam->bExit = FALSE; 262 263 if((NULL != pThread) && (NULL != pThread->m_hThread)) 264 { 265 WaitForSingleObject(pThread->m_hThread, INFINITE); 266 delete pThread; 267 pThread = NULL; 268 } 269 goto __CLEANUP__; 270 } 271 272 default: 273 break; 274 } 275 TranslateMessage(&msg); 276 DispatchMessage(&msg); 277 } 278 279 __CLEANUP__: 280 if(NULL != hWatchEvent) 281 { 282 CloseHandle(hWatchEvent); 283 hWatchEvent = NULL; 284 } 285 if(NULL != pBuffer) 286 { 287 delete[] pBuffer; 288 pBuffer = NULL; 289 } 290 if(NULL != pParam) 291 { 292 delete pParam; 293 pParam = NULL; 294 } 295 TRACE0("ThreadProc Thread Exit ... "); 296 return 0; 297 }
1 // 测试代码 2 3 #include "stdafx.h" 4 5 #include "DirectoryWatch.h" 6 7 void NotifyAction(DWORD dwAction, LPWSTR szFile, DWORD dwLength) 8 { 9 switch(dwAction) 10 { 11 case FILE_ACTION_ADDED: 12 wprintf(L"FILE_ACTION_ADDED: "); 13 break; 14 15 case FILE_ACTION_REMOVED: 16 wprintf(L"FILE_ACTION_REMOVED: "); 17 break; 18 19 case FILE_ACTION_MODIFIED: 20 wprintf(L"FILE_ACTION_MODIFIED: "); 21 break; 22 23 case FILE_ACTION_RENAMED_OLD_NAME: 24 wprintf(L"FILE_ACTION_RENAMED_OLD_NAME: "); 25 break; 26 27 case FILE_ACTION_RENAMED_NEW_NAME: 28 wprintf(L"FILE_ACTION_RENAMED_NEW_NAME: "); 29 break; 30 31 default: 32 break; 33 } 34 WCHAR szPath[MAX_PATH] = {0}; 35 wmemcpy(szPath, szFile, min(dwLength, MAX_PATH)); 36 wprintf(L"%s ", szPath); 37 } 38 39 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 40 { 41 CDirectoryWatch watch; 42 wprintf(L"Start Directory Watch ... "); 43 watch.StartDirectoryWatch(_T("F:\11"), NotifyAction); 44 Sleep(30 * 1000); 45 watch.StopDirectoryWatch(); 46 wprintf(L"Stop Directory Watch ... "); 47 48 Sleep(10 * 1000); 49 50 wprintf(L"Start Directory Watch ... "); 51 watch.StartDirectoryWatch(_T("F:\11"), NotifyAction); 52 Sleep(30 * 1000); 53 watch.StopDirectoryWatch(); 54 wprintf(L"Stop Directory Watch ... "); 55 Sleep(30 * 1000); 56 wprintf(L"Process Exit ... "); 57 return 0; 58 }
效果如下图所示:
[C++]使用ReadDirectoryChangesW API監控檔案系統的改變
[C++]使用ReadDirectoryChangesW API監控檔案系統的改變
在C++中若想要監控檔案系統改變有很多方法,可以用FindFirstChangeNotification取得檔案變更、或是Hook底層的API等方法來實現,這邊使用ReadDirectoryChangesW API來實現,該API使用前必須先加入Kernel32.lib。
並加入Windows.h的標頭檔
1 #include "Windows.h"
這些步驟做完後在程式中就可以看到ReadDirectoryChangesW API了,其函式原型如下:
1 BOOL WINAPI ReadDirectoryChangesW( 2 __in HANDLE hDirectory, 3 __out LPVOID lpBuffer, 4 __in DWORD nBufferLength, 5 __in BOOL bWatchSubtree, 6 __in DWORD dwNotifyFilter, 7 __out_opt LPDWORD lpBytesReturned, 8 __inout_opt LPOVERLAPPED lpOverlapped, 9 __in_opt LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine 10 );
該API必須帶入八個參數,hDirectory帶入的是要監控的目錄Handle、lpBuffer帶入的是用來回傳變動資料的空間、nBufferLength是lpBuffer空間的大小、bWatchSubtree是指定是否偵測子目錄、dwNotifyFilter是指定監控的目錄有哪些動作時需要通知、lpBytesReturned是用來回傳變動資料內含的長度、lpOverlapped可用來在非同步環境下使用重疊IO用、lpCompletionRoutine則是當監控完成或取消時所呼叫的回調函式。
其中dwNotifyFilter的值可設定的有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,詳細所代表的意義可參閱ReadDirectoryChangesW function。
了解了函式原型後,就可以開始進入實際的使用。剛有提到說在ReadDirectoryChangesW API函式必須要帶入的第一個參數是要監控的目錄Handle,所以我們必須透過CreateFile API取得要監控的目錄Handle,像是下面這樣:
1 HANDLE hDirectoryHandle = NULL; 2 3 4 hDirectoryHandle = ::CreateFileA( 5 file, 6 FILE_LIST_DIRECTORY, 7 FILE_SHARE_READ 8 | FILE_SHARE_WRITE 9 | FILE_SHARE_DELETE, 10 NULL, 11 OPEN_EXISTING, 12 FILE_FLAG_BACKUP_SEMANTICS 13 | FILE_FLAG_OVERLAPPED, 14 NULL); 15 16 if(hDirectoryHandle == INVALID_HANDLE_VALUE) 17 return;
取得監控的目錄Handle後,將其帶入ReadDirectoryChangesw API,順帶帶入像是回傳變動資料的Buffer空間、與要監控的變動類型等必要參數。像是下面這樣:
1 int nBufferSize = 1024; 2 char* buffer = new char[nBufferSize]; 3 DWORD dwBytes = 0; 4 5 memset(buffer, 0, nBufferSize); 6 7 if(!::ReadDirectoryChangesW( 8 hDirectoryHandle, 9 buffer, 10 nBufferSize, 11 bIncludeSubdirectories, 12 FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME, 13 &dwBytes, 14 NULL, 15 NULL) || GetLastError() == ERROR_INVALID_HANDLE) 16 { 17 break; 18 } 19 20 if(!dwBytes) 21 { 22 printf("Buffer overflow~~ "); 23 }
這邊需注意到的是,若是變動的資料太多,提供的存儲空間不足以存放時,回傳的變動資料長度會是0,此時所有變動資料都會丟失。這樣的情況多半只會出在一瞬間大量的變動,可以增大存儲空間或是減少監控的變動類型,以減少回傳的資料量,避免溢位的發生。
若是運行沒發生問題,變動的資料會存放在當初塞進去的存儲空間,該空間的資料其實是FILE_NOTIFY_INFORMATION structure的型態存在,因此我們可將存儲空間的資料轉換成PFILE_NOTIFY_INFORMATION。裡面的Action是我們所關注的變動類型,FileName是變動的檔案名稱,檔案名稱的部分是沒有結尾符號的,必須要搭配FileNameLength去截取。另外變動的資料有時候不止一筆,因此我們必須在這邊用迴圈搭配NextEntryOffset去重覆運行處理流程,處理所有變動的資料。
1 PFILE_NOTIFY_INFORMATION record = (PFILE_NOTIFY_INFORMATION)buffer; 2 DWORD cbOffset = 0; 3 4 do 5 { 6 switch (record->Action) 7 { 8 case FILE_ACTION_ADDED: 9 printf("FILE_ACTION_ADDED:"); 10 break; 11 case FILE_ACTION_REMOVED: 12 printf("FILE_ACTION_REMOVED:"); 13 break; 14 case FILE_ACTION_MODIFIED: 15 printf("FILE_ACTION_MODIFIED:"); 16 break; 17 case FILE_ACTION_RENAMED_OLD_NAME: 18 printf("FILE_ACTION_RENAMED_OLD_NAME:"); 19 break; 20 21 case FILE_ACTION_RENAMED_NEW_NAME: 22 printf("FILE_ACTION_RENAMED_NEW_NAME:"); 23 break; 24 25 default: 26 break; 27 } 28 29 char fileBuffer[512]; 30 31 WideCharToMultiByte(CP_ACP, 0, record->FileName, record->FileNameLength, fileBuffer, record->FileNameLength, NULL, NULL); 32 printf(fileBuffer); 33 printf(" "); 34 35 cbOffset = record->NextEntryOffset; 36 record = (PFILE_NOTIFY_INFORMATION)((LPBYTE) record + cbOffset); 37 }while(cbOffset);
這邊示範一個簡易的使用範例,實際使用時最好還是搭配執行緒處理:
1 // ConsoleApplication10.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include "Windows.h" 6 7 void MonitorDir(char* file, bool bIncludeSubdirectories = false) 8 { 9 int nBufferSize = 1024; 10 char* buffer = new char[nBufferSize]; 11 HANDLE hDirectoryHandle = NULL; 12 13 14 hDirectoryHandle = ::CreateFileA( 15 file, 16 FILE_LIST_DIRECTORY, 17 FILE_SHARE_READ 18 | FILE_SHARE_WRITE 19 | FILE_SHARE_DELETE, 20 NULL, 21 OPEN_EXISTING, 22 FILE_FLAG_BACKUP_SEMANTICS 23 | FILE_FLAG_OVERLAPPED, 24 NULL); 25 26 if(hDirectoryHandle == INVALID_HANDLE_VALUE) 27 return; 28 29 while(1) 30 { 31 DWORD dwBytes = 0; 32 33 memset(buffer, 0, nBufferSize); 34 35 if(!::ReadDirectoryChangesW( 36 hDirectoryHandle, 37 buffer, 38 nBufferSize, 39 bIncludeSubdirectories, 40 FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME, 41 &dwBytes, 42 NULL, 43 NULL) || GetLastError() == ERROR_INVALID_HANDLE) 44 { 45 break; 46 } 47 48 if(!dwBytes) 49 { 50 printf("Buffer overflow~~ "); 51 } 52 53 PFILE_NOTIFY_INFORMATION record = (PFILE_NOTIFY_INFORMATION)buffer; 54 DWORD cbOffset = 0; 55 56 do 57 { 58 switch (record->Action) 59 { 60 case FILE_ACTION_ADDED: 61 printf("FILE_ACTION_ADDED:"); 62 break; 63 case FILE_ACTION_REMOVED: 64 printf("FILE_ACTION_REMOVED:"); 65 break; 66 case FILE_ACTION_MODIFIED: 67 printf("FILE_ACTION_MODIFIED:"); 68 break; 69 case FILE_ACTION_RENAMED_OLD_NAME: 70 printf("FILE_ACTION_RENAMED_OLD_NAME:"); 71 break; 72 73 case FILE_ACTION_RENAMED_NEW_NAME: 74 printf("FILE_ACTION_RENAMED_NEW_NAME:"); 75 break; 76 77 default: 78 break; 79 } 80 81 char fileBuffer[512]; 82 83 WideCharToMultiByte(CP_ACP, 0, record->FileName, record->FileNameLength, fileBuffer, record->FileNameLength, NULL, NULL); 84 printf(fileBuffer); 85 printf(" "); 86 87 cbOffset = record->NextEntryOffset; 88 record = (PFILE_NOTIFY_INFORMATION)((LPBYTE) record + cbOffset); 89 }while(cbOffset); 90 } 91 92 delete buffer; 93 94 if(hDirectoryHandle) 95 CloseHandle(hDirectoryHandle); 96 } 97 98 int _tmain(int argc, _TCHAR* argv[]) 99 { 100 MonitorDir("C:\Users\larry\Desktop\新增資料夾");
運行後去對監控的目錄操作~可得到類似如下的結果: