ReadDirectoryChangesW 监控文件夹 (一个简单的监控示例程序)

来源:互联网 发布:数据的分类汇总教案 编辑:程序博客网 时间:2024/06/11 23:21
// .h文件#pragma oncetypedef void (*PFN_NotifyAction)(DWORD dwAction, LPWSTR szFile, DWORD dwLength);class CDirectoryWatch{public:CDirectoryWatch(void);virtual ~CDirectoryWatch(void);public:BOOL StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction);BOOL StopDirectoryWatch(void);private:static UINT __cdecl ThreadProc(LPVOID lParam);static UINT __cdecl DirectoryWatch(LPVOID lParam);private:HANDLE m_hFile;CWinThread* m_pThread;TCHAR m_szDirectory[MAX_PATH];};
// .cpp文件#include "StdAfx.h"#include "DirectoryWatch.h"#include <strsafe.h>typedef enum{MSG_STARTWATCH = (WM_USER + 0x11),MSG_STOPWATCH,MSG_EXITTHREAD};#define MAX_BUFFER_SIZE(1024)typedef struct _tagWATCHPARAMETERS{_tagWATCHPARAMETERS(){hFile = INVALID_HANDLE_VALUE;hEvent = NULL;memset(&ol, 0, sizeof(OVERLAPPED));pBuffer = NULL;dwBufferSize = 0;bExit = FALSE;pFn_NotifyAction = NULL;}HANDLE hFile;HANDLE hEvent;OVERLAPPED ol;BYTE* pBuffer;DWORD dwBufferSize;BOOL bExit;PFN_NotifyAction pFn_NotifyAction;}WATCH_PARAMETERS, *PWATCH_PARAMETERS;CDirectoryWatch::CDirectoryWatch() : m_hFile(INVALID_HANDLE_VALUE), m_pThread(NULL){memset(m_szDirectory, 0, sizeof(m_szDirectory));m_pThread = AfxBeginThread(ThreadProc, NULL, 0, CREATE_SUSPENDED, 0, NULL);if(NULL == m_pThread){TRACE("Error Code : %d\n", GetLastError());return ;}m_pThread->m_bAutoDelete = FALSE;m_pThread->ResumeThread();}CDirectoryWatch::~CDirectoryWatch(){if(INVALID_HANDLE_VALUE != m_hFile){CloseHandle(m_hFile);m_hFile = INVALID_HANDLE_VALUE;}if((NULL != m_pThread) && (NULL != m_pThread->m_hThread)){m_pThread->PostThreadMessage(MSG_EXITTHREAD, 0, 0);WaitForSingleObject(m_pThread->m_hThread, INFINITE);delete m_pThread;m_pThread = NULL;}}BOOL CDirectoryWatch::StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction){if(NULL == m_pThread){return FALSE;}if(NULL == lpszDirectory){return FALSE;}if(NULL == pFn_NotifyAction){return FALSE;}if(!PathFileExists(lpszDirectory)){TRACE("Error Code : %d\n", GetLastError());return FALSE;}if(!PathIsDirectory(lpszDirectory)){TRACE("Error Code : %d\n", GetLastError());return FALSE;}if(0 == _tcslen(m_szDirectory)){StringCchPrintf(m_szDirectory, _countof(m_szDirectory), _T("%s"), lpszDirectory);}else if(CSTR_EQUAL != CompareStringOrdinal(m_szDirectory, -1, lpszDirectory, -1, TRUE)){TRACE("Not Change Directory.\n");return FALSE;}if(INVALID_HANDLE_VALUE == m_hFile){m_hFile = CreateFile(lpszDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);if(INVALID_HANDLE_VALUE == m_hFile){TRACE("Error Code : %d\n", GetLastError());return FALSE;}}return m_pThread->PostThreadMessage(MSG_STARTWATCH, (WPARAM)m_hFile, (LPARAM)pFn_NotifyAction);}BOOL CDirectoryWatch::StopDirectoryWatch(){if(NULL != m_pThread){return m_pThread->PostThreadMessage(MSG_STOPWATCH, 0, 0);}return FALSE;}UINT __cdecl CDirectoryWatch::DirectoryWatch(LPVOID lParam){WATCH_PARAMETERS* pParam = (WATCH_PARAMETERS*)lParam;if(NULL == pParam){return 0;}HANDLE& hFile = pParam->hFile;BYTE* pBuffer = pParam->pBuffer;DWORD dwBufferSize = pParam->dwBufferSize;OVERLAPPED& ol = pParam->ol;HANDLE& hEvent = pParam->hEvent;BOOL& bExit = pParam->bExit;PFN_NotifyAction pFn_NotifyAction = pParam->pFn_NotifyAction;DWORD dwBytesReturn = 0;DWORD dwRet = WAIT_FAILED;DWORD dwOffSet = 0;TCHAR szFile[MAX_PATH] = {0};while(TRUE){if(WAIT_OBJECT_0 != WaitForSingleObject(hEvent, INFINITE)){TRACE("Error Code : %d\n", GetLastError());break;}if(bExit){break;}if(!ReadDirectoryChangesW(hFile, pBuffer, dwBufferSize, TRUE, 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, &dwBytesReturn, &ol, NULL)){TRACE("Error Code : %d\n", GetLastError());break;}if(!GetOverlappedResult(hFile, &ol, &dwBytesReturn, TRUE)){TRACE("Error Code : %d\n", GetLastError());break;}FILE_NOTIFY_INFORMATION* pFileNotify = (FILE_NOTIFY_INFORMATION*)pBuffer;do {if(pFn_NotifyAction && (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0))){pFn_NotifyAction(pFileNotify->Action, pFileNotify->FileName, (pFileNotify->FileNameLength) / sizeof(WCHAR));}dwOffSet = pFileNotify->NextEntryOffset;pFileNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pFileNotify + dwOffSet);} while (dwOffSet);}TRACE0("DirectoryWatch Thread Exit ... \n");return 0;}UINT __cdecl CDirectoryWatch::ThreadProc(LPVOID lParam){WATCH_PARAMETERS* pParam = new WATCH_PARAMETERS;if(NULL == pParam){goto __CLEANUP__;}BYTE* pBuffer = new BYTE[MAX_BUFFER_SIZE];if(NULL == pBuffer){goto __CLEANUP__;}memset(pBuffer, 0, MAX_BUFFER_SIZE);pParam->pBuffer = pBuffer;pParam->dwBufferSize = MAX_BUFFER_SIZE;HANDLE hWatchEvent  = CreateEvent(NULL, TRUE, FALSE, NULL);if(NULL == hWatchEvent){goto __CLEANUP__;}pParam->ol.hEvent = hWatchEvent;CWinThread* pThread = NULL;HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if(NULL == hEvent){goto __CLEANUP__;}pParam->hEvent = hEvent;MSG msg;while(GetMessage(&msg, NULL, 0, 0)){switch(msg.message){case MSG_STARTWATCH:{HANDLE hFile = (HANDLE)(msg.wParam);PFN_NotifyAction pFn_NotifyAction = (PFN_NotifyAction)(msg.lParam);if((INVALID_HANDLE_VALUE == hFile) && (NULL == pFn_NotifyAction)){break;}if(NULL == pThread){pParam->hFile = hFile;pParam->pFn_NotifyAction = pFn_NotifyAction;pThread = AfxBeginThread(DirectoryWatch, (LPVOID)pParam, 0, CREATE_SUSPENDED, NULL);if(NULL == pThread){goto __CLEANUP__;}pThread->m_bAutoDelete = FALSE;pThread->ResumeThread();}SetEvent(hEvent);}break;case MSG_STOPWATCH:{ResetEvent(hEvent);}break;case MSG_EXITTHREAD:{SetEvent(hEvent);pParam->bExit = FALSE;if((NULL != pThread) && (NULL != pThread->m_hThread)){WaitForSingleObject(pThread->m_hThread, INFINITE);delete pThread;pThread = NULL;}goto __CLEANUP__;}default:break;}TranslateMessage(&msg);DispatchMessage(&msg);}__CLEANUP__:if(NULL != hWatchEvent){CloseHandle(hWatchEvent);hWatchEvent = NULL;}if(NULL != pBuffer){delete[] pBuffer;pBuffer = NULL;}if(NULL != pParam){delete pParam;pParam = NULL;}TRACE0("ThreadProc Thread Exit ...\n");return 0;}
// 测试代码#include "stdafx.h"#include "DirectoryWatch.h"void NotifyAction(DWORD dwAction, LPWSTR szFile, DWORD dwLength){switch(dwAction){case FILE_ACTION_ADDED:wprintf(L"FILE_ACTION_ADDED: \n\t");break;case FILE_ACTION_REMOVED:wprintf(L"FILE_ACTION_REMOVED: \n\t");break;case FILE_ACTION_MODIFIED:wprintf(L"FILE_ACTION_MODIFIED: \n\t");break;case FILE_ACTION_RENAMED_OLD_NAME:wprintf(L"FILE_ACTION_RENAMED_OLD_NAME: \n\t");break;case FILE_ACTION_RENAMED_NEW_NAME:wprintf(L"FILE_ACTION_RENAMED_NEW_NAME: \n\t");break;default:break;}WCHAR szPath[MAX_PATH] = {0};wmemcpy(szPath, szFile, min(dwLength, MAX_PATH));wprintf(L"%s\n", szPath);}int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){CDirectoryWatch watch;wprintf(L"Start Directory Watch ...\n");watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);Sleep(30 * 1000);watch.StopDirectoryWatch();wprintf(L"Stop Directory Watch ...\n");Sleep(10 * 1000);wprintf(L"Start Directory Watch ...\n");watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);Sleep(30 * 1000);watch.StopDirectoryWatch();wprintf(L"Stop Directory Watch ...\n");Sleep(30 * 1000);wprintf(L"Process Exit ...\n");return 0;}
效果如下图所示:
原创粉丝点击