1. // .h文件
  2. #pragma once
  3. typedef void (*PFN_NotifyAction)(DWORD dwAction, LPWSTR szFile, DWORD dwLength);
  4. class CDirectoryWatch
  5. {
  6. public:
  7. CDirectoryWatch(void);
  8. virtual ~CDirectoryWatch(void);
  9. public:
  10. BOOL StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction);
  11. BOOL StopDirectoryWatch(void);
  12. private:
  13. static UINT __cdecl ThreadProc(LPVOID lParam);
  14. static UINT __cdecl DirectoryWatch(LPVOID lParam);
  15. private:
  16. HANDLE m_hFile;
  17. CWinThread* m_pThread;
  18. TCHAR m_szDirectory[MAX_PATH];
  19. };
  1. // .cpp文件
  2. #include "StdAfx.h"
  3. #include "DirectoryWatch.h"
  4. #include <strsafe.h>
  5. typedef enum
  6. {
  7. MSG_STARTWATCH = (WM_USER + 0x11),
  8. MSG_STOPWATCH,
  9. MSG_EXITTHREAD
  10. };
  11. #define MAX_BUFFER_SIZE (1024)
  12. typedef struct _tagWATCHPARAMETERS
  13. {
  14. _tagWATCHPARAMETERS()
  15. {
  16. hFile = INVALID_HANDLE_VALUE;
  17. hEvent = NULL;
  18. memset(&ol, 0, sizeof(OVERLAPPED));
  19. pBuffer = NULL;
  20. dwBufferSize = 0;
  21. bExit = FALSE;
  22. pFn_NotifyAction = NULL;
  23. }
  24. HANDLE hFile;
  25. HANDLE hEvent;
  26. OVERLAPPED ol;
  27. BYTE* pBuffer;
  28. DWORD dwBufferSize;
  29. BOOL bExit;
  30. PFN_NotifyAction pFn_NotifyAction;
  31. }WATCH_PARAMETERS, *PWATCH_PARAMETERS;
  32. CDirectoryWatch::CDirectoryWatch() : m_hFile(INVALID_HANDLE_VALUE), m_pThread(NULL)
  33. {
  34. memset(m_szDirectory, 0, sizeof(m_szDirectory));
  35. m_pThread = AfxBeginThread(ThreadProc, NULL, 0, CREATE_SUSPENDED, 0, NULL);
  36. if(NULL == m_pThread)
  37. {
  38. TRACE("Error Code : %d\n", GetLastError());
  39. return ;
  40. }
  41. m_pThread->m_bAutoDelete = FALSE;
  42. m_pThread->ResumeThread();
  43. }
  44. CDirectoryWatch::~CDirectoryWatch()
  45. {
  46. if(INVALID_HANDLE_VALUE != m_hFile)
  47. {
  48. CloseHandle(m_hFile);
  49. m_hFile = INVALID_HANDLE_VALUE;
  50. }
  51. if((NULL != m_pThread) && (NULL != m_pThread->m_hThread))
  52. {
  53. m_pThread->PostThreadMessage(MSG_EXITTHREAD, 0, 0);
  54. WaitForSingleObject(m_pThread->m_hThread, INFINITE);
  55. delete m_pThread;
  56. m_pThread = NULL;
  57. }
  58. }
  59. BOOL CDirectoryWatch::StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction)
  60. {
  61. if(NULL == m_pThread)
  62. {
  63. return FALSE;
  64. }
  65. if(NULL == lpszDirectory)
  66. {
  67. return FALSE;
  68. }
  69. if(NULL == pFn_NotifyAction)
  70. {
  71. return FALSE;
  72. }
  73. if(!PathFileExists(lpszDirectory))
  74. {
  75. TRACE("Error Code : %d\n", GetLastError());
  76. return FALSE;
  77. }
  78. if(!PathIsDirectory(lpszDirectory))
  79. {
  80. TRACE("Error Code : %d\n", GetLastError());
  81. return FALSE;
  82. }
  83. if(0 == _tcslen(m_szDirectory))
  84. {
  85. StringCchPrintf(m_szDirectory, _countof(m_szDirectory), _T("%s"), lpszDirectory);
  86. }
  87. else if(CSTR_EQUAL != CompareStringOrdinal(m_szDirectory, -1, lpszDirectory, -1, TRUE))
  88. {
  89. TRACE("Not Change Directory.\n");
  90. return FALSE;
  91. }
  92. if(INVALID_HANDLE_VALUE == m_hFile)
  93. {
  94. m_hFile = CreateFile(lpszDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  95. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
  96. if(INVALID_HANDLE_VALUE == m_hFile)
  97. {
  98. TRACE("Error Code : %d\n", GetLastError());
  99. return FALSE;
  100. }
  101. }
  102. return m_pThread->PostThreadMessage(MSG_STARTWATCH, (WPARAM)m_hFile, (LPARAM)pFn_NotifyAction);
  103. }
  104. BOOL CDirectoryWatch::StopDirectoryWatch()
  105. {
  106. if(NULL != m_pThread)
  107. {
  108. return m_pThread->PostThreadMessage(MSG_STOPWATCH, 0, 0);
  109. }
  110. return FALSE;
  111. }
  112. UINT __cdecl CDirectoryWatch::DirectoryWatch(LPVOID lParam)
  113. {
  114. WATCH_PARAMETERS* pParam = (WATCH_PARAMETERS*)lParam;
  115. if(NULL == pParam)
  116. {
  117. return 0;
  118. }
  119. HANDLE& hFile = pParam->hFile;
  120. BYTE* pBuffer = pParam->pBuffer;
  121. DWORD dwBufferSize = pParam->dwBufferSize;
  122. OVERLAPPED& ol = pParam->ol;
  123. HANDLE& hEvent = pParam->hEvent;
  124. BOOL& bExit = pParam->bExit;
  125. PFN_NotifyAction pFn_NotifyAction = pParam->pFn_NotifyAction;
  126. DWORD dwBytesReturn = 0;
  127. DWORD dwRet = WAIT_FAILED;
  128. DWORD dwOffSet = 0;
  129. TCHAR szFile[MAX_PATH] = {0};
  130. while(TRUE)
  131. {
  132. if(WAIT_OBJECT_0 != WaitForSingleObject(hEvent, INFINITE))
  133. {
  134. TRACE("Error Code : %d\n", GetLastError());
  135. break;
  136. }
  137. if(bExit)
  138. {
  139. break;
  140. }
  141. if(!ReadDirectoryChangesW(hFile, pBuffer, dwBufferSize, TRUE,
  142. FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES
  143. | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS
  144. | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, &dwBytesReturn, &ol, NULL))
  145. {
  146. TRACE("Error Code : %d\n", GetLastError());
  147. break;
  148. }
  149. if(!GetOverlappedResult(hFile, &ol, &dwBytesReturn, TRUE))
  150. {
  151. TRACE("Error Code : %d\n", GetLastError());
  152. break;
  153. }
  154. FILE_NOTIFY_INFORMATION* pFileNotify = (FILE_NOTIFY_INFORMATION*)pBuffer;
  155. do
  156. {
  157. if(pFn_NotifyAction && (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0)))
  158. {
  159. pFn_NotifyAction(pFileNotify->Action, pFileNotify->FileName, (pFileNotify->FileNameLength) / sizeof(WCHAR));
  160. }
  161. dwOffSet = pFileNotify->NextEntryOffset;
  162. pFileNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pFileNotify + dwOffSet);
  163. } while (dwOffSet);
  164. }
  165. TRACE0("DirectoryWatch Thread Exit ... \n");
  166. return 0;
  167. }
  168. UINT __cdecl CDirectoryWatch::ThreadProc(LPVOID lParam)
  169. {
  170. WATCH_PARAMETERS* pParam = new WATCH_PARAMETERS;
  171. if(NULL == pParam)
  172. {
  173. goto __CLEANUP__;
  174. }
  175. BYTE* pBuffer = new BYTE[MAX_BUFFER_SIZE];
  176. if(NULL == pBuffer)
  177. {
  178. goto __CLEANUP__;
  179. }
  180. memset(pBuffer, 0, MAX_BUFFER_SIZE);
  181. pParam->pBuffer = pBuffer;
  182. pParam->dwBufferSize = MAX_BUFFER_SIZE;
  183. HANDLE hWatchEvent  = CreateEvent(NULL, TRUE, FALSE, NULL);
  184. if(NULL == hWatchEvent)
  185. {
  186. goto __CLEANUP__;
  187. }
  188. pParam->ol.hEvent = hWatchEvent;
  189. CWinThread* pThread = NULL;
  190. HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  191. if(NULL == hEvent)
  192. {
  193. goto __CLEANUP__;
  194. }
  195. pParam->hEvent = hEvent;
  196. MSG msg;
  197. while(GetMessage(&msg, NULL, 0, 0))
  198. {
  199. switch(msg.message)
  200. {
  201. case MSG_STARTWATCH:
  202. {
  203. HANDLE hFile = (HANDLE)(msg.wParam);
  204. PFN_NotifyAction pFn_NotifyAction = (PFN_NotifyAction)(msg.lParam);
  205. if((INVALID_HANDLE_VALUE == hFile) && (NULL == pFn_NotifyAction))
  206. {
  207. break;
  208. }
  209. if(NULL == pThread)
  210. {
  211. pParam->hFile = hFile;
  212. pParam->pFn_NotifyAction = pFn_NotifyAction;
  213. pThread = AfxBeginThread(DirectoryWatch, (LPVOID)pParam, 0, CREATE_SUSPENDED, NULL);
  214. if(NULL == pThread)
  215. {
  216. goto __CLEANUP__;
  217. }
  218. pThread->m_bAutoDelete = FALSE;
  219. pThread->ResumeThread();
  220. }
  221. SetEvent(hEvent);
  222. }
  223. break;
  224. case MSG_STOPWATCH:
  225. {
  226. ResetEvent(hEvent);
  227. }
  228. break;
  229. case MSG_EXITTHREAD:
  230. {
  231. SetEvent(hEvent);
  232. pParam->bExit = FALSE;
  233. if((NULL != pThread) && (NULL != pThread->m_hThread))
  234. {
  235. WaitForSingleObject(pThread->m_hThread, INFINITE);
  236. delete pThread;
  237. pThread = NULL;
  238. }
  239. goto __CLEANUP__;
  240. }
  241. default:
  242. break;
  243. }
  244. TranslateMessage(&msg);
  245. DispatchMessage(&msg);
  246. }
  247. __CLEANUP__:
  248. if(NULL != hWatchEvent)
  249. {
  250. CloseHandle(hWatchEvent);
  251. hWatchEvent = NULL;
  252. }
  253. if(NULL != pBuffer)
  254. {
  255. delete[] pBuffer;
  256. pBuffer = NULL;
  257. }
  258. if(NULL != pParam)
  259. {
  260. delete pParam;
  261. pParam = NULL;
  262. }
  263. TRACE0("ThreadProc Thread Exit ...\n");
  264. return 0;
  265. }
  1. // 测试代码
  2. #include "stdafx.h"
  3. #include "DirectoryWatch.h"
  4. void NotifyAction(DWORD dwAction, LPWSTR szFile, DWORD dwLength)
  5. {
  6. switch(dwAction)
  7. {
  8. case FILE_ACTION_ADDED:
  9. wprintf(L"FILE_ACTION_ADDED: \n\t");
  10. break;
  11. case FILE_ACTION_REMOVED:
  12. wprintf(L"FILE_ACTION_REMOVED: \n\t");
  13. break;
  14. case FILE_ACTION_MODIFIED:
  15. wprintf(L"FILE_ACTION_MODIFIED: \n\t");
  16. break;
  17. case FILE_ACTION_RENAMED_OLD_NAME:
  18. wprintf(L"FILE_ACTION_RENAMED_OLD_NAME: \n\t");
  19. break;
  20. case FILE_ACTION_RENAMED_NEW_NAME:
  21. wprintf(L"FILE_ACTION_RENAMED_NEW_NAME: \n\t");
  22. break;
  23. default:
  24. break;
  25. }
  26. WCHAR szPath[MAX_PATH] = {0};
  27. wmemcpy(szPath, szFile, min(dwLength, MAX_PATH));
  28. wprintf(L"%s\n", szPath);
  29. }
  30. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  31. {
  32. CDirectoryWatch watch;
  33. wprintf(L"Start Directory Watch ...\n");
  34. watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);
  35. Sleep(30 * 1000);
  36. watch.StopDirectoryWatch();
  37. wprintf(L"Stop Directory Watch ...\n");
  38. Sleep(10 * 1000);
  39. wprintf(L"Start Directory Watch ...\n");
  40. watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);
  41. Sleep(30 * 1000);
  42. watch.StopDirectoryWatch();
  43. wprintf(L"Stop Directory Watch ...\n");
  44. Sleep(30 * 1000);
  45. wprintf(L"Process Exit ...\n");
  46. return 0;
  47. }

效果如下图所示:

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

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

  1. gulp插件实现压缩一个文件夹下不同目录下的js文件(支持es6)

    gulp-uglify:压缩js大小,只支持es5 安装: cnpm: cnpm i gulp-uglify -D yarn: yarn add gulp-uglify -D 使用: 代码实现1:压缩 ...

  2. META-INF文件夹是干啥的,META-INF文件夹的作用, META-INF文件夹能删吗

    今天有人问到 META-INF文件夹是干啥的,META-INF文件夹的作用, META-INF文件夹能删吗,还有项目的META-INF下面一般会有个MANIFEST.MF 文件,都是干啥的. 百度搜了 ...

  3. selector是在文件夹drawable中进行定义的xml文件。

    获取Drawable对象: Resources res = mContext.getResources(); Drawable myImage = res.getDrawable(R.drawable ...

  4. 导出不带.svn的文件夹或者是不含.class的文件

    转载自:http://blog.csdn.net/z278718149/article/details/21537395 如何导出不带.svn的文件夹或者是不含.class的文件 在工作环境中,有的时 ...

  5. selector是在文件夹drawable中进行定义的xml文件转载 https://www.cnblogs.com/fx2008/p/3157040.html

    获取Drawable对象: Resources res = mContext.getResources(); Drawable myImage = res.getDrawable(R.drawable ...

  6. 一个简单的P2P传输程序

    写了一个简单的P2P传输程序,在P2P的圈子中传输文件,不过为了简便,这个程序没有真正的传输文件,只是简单的判断一下文件的位置在哪里.这个程序可以处理当有一个peer闪退的情况,在这种情况下,剩下的p ...

  7. Android加载SD卡目录,文件夹遍历,图片设置,设置文件对应打开方式等

    此案例主要说的是Android使用GridView加载SD卡下所有目录,文件夹多层遍历,文件图标修改,设置文件对应打开方式等功能. 如图: 代码: public class GridViewFile ...

  8. IOS开发之小实例--使用UIImagePickerController创建一个简单的相机应用程序

    前言:本篇博文是本人阅读国外的IOS Programming Tutorial的一篇入门文章的学习过程总结,难度不大,因为是入门.主要是入门UIImagePickerController这个控制器,那 ...

  9. iOS开发UI篇—使用嵌套模型完成的一个简单汽车图标展示程序

    iOS开发UI篇—使用嵌套模型完成的一个简单汽车图标展示程序 一.plist文件和项目结构图 说明:这是一个嵌套模型的示例 二.代码示例: YYcarsgroup.h文件代码: // // YYcar ...

随机推荐

  1. 【转载】mysqldump的single-transaction和master-data

    原文地址:mysqldump的single-transaction和master-data 作者:myownstars 先看一下--lock-tables和--lock-all-tables --lo ...

  2. IBM MQ Reason 2538(MQRC_HOST_NOT_AVAILABLE) 错误原因一例

    环境: .NET 4.0, MQ .NET客户端 IBM.XMS(v2.0.0.3) 测试代码如下: var factoryFactory = XMSFactoryFactory.GetInstanc ...

  3. netlink---Linux下基于socket的内核和上层通信机制 (转)

    需要在linux网卡 驱动中加入一个自己的驱动,实现在内核态完成一些报文处理(这个过程可以实现一种零COPY的网络报文截获),对于复杂报文COPY下必要的数据交给用户 态来完成(因为过于复杂的报文消耗 ...

  4. MVC学习系列——记一次失败面试后,感想。

    在此写博客之际,热烈庆祝母校苏州科技学院,正式改名为苏州科技大学. 一晃眼,从自己投身IT行业已经两年有余,期间经历了结婚.买房等人生大事,非常感谢我的老婆,谢谢她这么爱我,嫁给我这个码农,呵呵... ...

  5. vc2005 编译ACE-6.2.0

    vc2005 编译ACE-6.2.0 下载并解压ACE-6.2.0 ftp://download.dre.vanderbilt.edu/previous_versions/ACE-6.2.0.zip ...

  6. UML 小结(5)- 图解 Rational Rose 的详细安装过程

    在学习UML的时候,会用到画图工具:Rotional Rose . 原以为这款软件直接下载下来或者跟朋友那边拷过来就可以直接用了,结果却是没有那么简单,如果读者您也是为了解决这个家伙的安装问题的话,那 ...

  7. what are Datatypes in SQLite supporting android

    As said at Datatypes In SQLite Version 3: Datatypes In SQLite Version 3 Most SQL database engines (e ...

  8. 线性判别分析(LDA), 主成分分析(PCA)及其推导【转】

    前言: 如果学习分类算法,最好从线性的入手,线性分类器最简单的就是LDA,它可以看做是简化版的SVM,如果想理解SVM这种分类器,那理解LDA就是很有必要的了. 谈到LDA,就不得不谈谈PCA,PCA ...

  9. ETL Pentaho Data Integration (Kettle) 插入/更新 问题 etl

    Pentaho Data Integration (Kettle) 使用此工具 按 索引  做 插入更新操作时,也可能报 索引重复 的错误, 解决方法:  匹配的索引字段可能有null值,会导致此错误 ...

  10. c++ 原子操作

    转载自: http://blog.csdn.net/yockie/article/details/8838686 所谓的原子操作,取的就是“原子是最小的.不可分割的最小个体”的意义,它表示在多个线程访 ...