ReadDirectoryChangesW 监控文件夹 (一个简单的监控示例程序)(文件被修改了,也可以探测到)

[cpp] view plain copy
 
  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. };  
[cpp] view plain copy
 
  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. }  
[cpp] view plain copy
 
  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. }  

效果如下图所示:

 

http://blog.csdn.net/visualeleven/article/details/7562014

posted @ 2016-10-26 20:11  findumars  Views(1321)  Comments(0Edit  收藏  举报