VC++ 监控指定目录改变
轉載: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\r\n"); ????????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 (添加文件)- \r\n"); ????????????????break; ????????????case?FILE_ACTION_REMOVED: ????????????????dlg->m_edit.ReplaceSel("Directory/File removed (刪除文件)- \r\n"); ????????????????break; ????????????case?FILE_ACTION_MODIFIED: ????????????????dlg->m_edit.ReplaceSel("Directory/File modified (修改文件內容)- \r\n"); ????????????????break; ????????????case?FILE_ACTION_RENAMED_OLD_NAME: ????????????????dlg->m_edit.ReplaceSel("Directory/File old name (修改文件名字)- \r\n"); ????????????????break; ????????????case?FILE_ACTION_RENAMED_NEW_NAME: ????????????????dlg->m_edit.ReplaceSel("Directory/File new name - \r\n"); ????????????????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)
| 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\n", 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\n", GetLastError()); 89 return FALSE; 90 } 91 92 if(!PathIsDirectory(lpszDirectory)) 93 { 94 TRACE("Error Code : %d\n", 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.\n"); 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\n", 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\n", 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\n", GetLastError()); 169 break; 170 } 171 if(!GetOverlappedResult(hFile, &ol, &dwBytesReturn, TRUE)) 172 { 173 TRACE("Error Code : %d\n", 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 ... \n"); 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 ...\n"); 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: \n\t"); 13 break; 14 15 case FILE_ACTION_REMOVED: 16 wprintf(L"FILE_ACTION_REMOVED: \n\t"); 17 break; 18 19 case FILE_ACTION_MODIFIED: 20 wprintf(L"FILE_ACTION_MODIFIED: \n\t"); 21 break; 22 23 case FILE_ACTION_RENAMED_OLD_NAME: 24 wprintf(L"FILE_ACTION_RENAMED_OLD_NAME: \n\t"); 25 break; 26 27 case FILE_ACTION_RENAMED_NEW_NAME: 28 wprintf(L"FILE_ACTION_RENAMED_NEW_NAME: \n\t"); 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\n", szPath); 37 } 38 39 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 40 { 41 CDirectoryWatch watch; 42 wprintf(L"Start Directory Watch ...\n"); 43 watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction); 44 Sleep(30 * 1000); 45 watch.StopDirectoryWatch(); 46 wprintf(L"Stop Directory Watch ...\n"); 47 48 Sleep(10 * 1000); 49 50 wprintf(L"Start Directory Watch ...\n"); 51 watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction); 52 Sleep(30 * 1000); 53 watch.StopDirectoryWatch(); 54 wprintf(L"Stop Directory Watch ...\n"); 55 Sleep(30 * 1000); 56 wprintf(L"Process Exit ...\n"); 57 return 0; 58 }效果如下圖所示:
?
2011-11-13[C++]使用ReadDirectoryChangesW API監控檔案系統的改變
- 43195
- ?0
- C++
- ?檢舉文章
- ?2013-08-28
[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~~\r\n"); 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("\r\n"); 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~~\r\n"); 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("\r\n"); 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\\新增資料夾");?
??
運行後去對監控的目錄操作~可得到類似如下的結果:
總結
以上是生活随笔為你收集整理的VC++ 监控指定目录改变的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于MySql数据库设计表与查询耗时分析
- 下一篇: C++ 类里面,函数占用存储空间问题