码迷,mamicode.com
首页 > 编程语言 > 详细

VC++ 监控指定目录改变

时间:2016-03-17 19:33:19      阅读:731      评论:0      收藏:0      [点我收藏+]

标签:

转载: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, &notify, 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)

ValueMeaning

FILE_ACTION_ADDED
0x00000001

The file was added to the directory.

FILE_ACTION_REMOVED
0x00000002

The file was removed from the directory.

FILE_ACTION_MODIFIED
0x00000003

The file was modified. This can be a change in the time stamp or attributes.

FILE_ACTION_RENAMED_OLD_NAME
0x00000004

The file was renamed and this is the old name.

FILE_ACTION_RENAMED_NEW_NAME
0x00000005

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 }

效果如下图所示:

技术分享

VC++ 监控指定目录改变

标签:

原文地址:http://www.cnblogs.com/chechen/p/5288444.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!