监控注册表键的改动,也可以监控文件夹,用法很简单:
1////////////////////////////////////////////////
2changenotify.h
3
4#pragma once
5
6#define WM_MONITER( WM_USER + 1000 )
7#define WM_MONITER_EXIT( WM_MONITER + 1 )
8#define WM_MONITER_FILE( WM_MONITER + 2 )
9
10#define ERROR_NOTIFY100000L
11#define ERROR_NOTIFY_ALREADY_START( ERROR_NOTIFY + 1 )
12
13
14DWORD CALLBACK ChangeMonitorThread( LPVOID pParam );
15class CChangeMonitor
16{
17public:
18CChangeMonitor();
19virtual ~CChangeMonitor();
20virtual BOOL StartMoniter( HWND hWnd );
21virtual void EndMoniter( void );
22protected:
23virtual void SendNotify( UINT nMsg );
24virtual void CallNextMoniter( void ) = 0;
25virtual DWORD WaitNotify( void ) = 0;
26protected:
27HANDLE m_hThread;
28HWND m_hWnd;
29DWORD m_dwThreadId;
30
31friend DWORD CALLBACK ChangeMonitorThread( LPVOID pParam );
32};
33
34
35
36class CDirectoryMonitor : public CChangeMonitor
37{
38public:
39CDirectoryMonitor();
40~CDirectoryMonitor();
41BOOL StartMoniter( HWND hWnd, LPCTSTR lpPath, BOOL bSubTree = TRUE,
42DWORD dwFilter = FILE_NOTIFY_CHANGE_LAST_WRITE );
43void EndMoniter( void );
44protected:
45virtual void CallNextMoniter( void );
46virtual DWORD WaitNotify( void );
47protected:
48HANDLE m_hNotify;
49};
50
51
52class CRegistryMonitor : public CChangeMonitor
53{
54public:
55CRegistryMonitor();
56~CRegistryMonitor();
57BOOL StartMoniter( HWND hWnd, HKEY hRoot, LPCTSTR lpSubKey,
58DWORD dwFilter = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET );
59void EndMoniter( void );
60protected:
61virtual void CallNextMoniter( void );
62virtual DWORD WaitNotify( void );
63protected:
64HANDLE m_hNotify;
65HKEY m_hKey;
66DWORD m_dwFilter;
67};
68
69
70
71
72//////////////////////////////////////////////////////
73changenotify.cpp
74
75#include "ChangeNotify.h"
76
77CChangeMonitor::CChangeMonitor( void )
78: m_hThread( NULL )
79, m_hWnd( NULL )
80, m_dwThreadId( 0 )
81{
82}
83
84CChangeMonitor::~CChangeMonitor( void )
85{
86EndMoniter();
87}
88
89BOOL CChangeMonitor::StartMoniter( HWND hWnd )
90{
91// 判断是否已经启动监视
92if ( NULL != m_hThread )
93{
94SetLastError( ERROR_NOTIFY_ALREADY_START );
95TRACE_ERROR( GetLastError() );
96return FALSE;
97}
98// 检查参数
99if ( NULL == hWnd )
100{
101SetLastError( ERROR_INVALID_PARAMETER );
102TRACE_ERROR( GetLastError() );
103return FALSE;
104}
105m_hWnd = hWnd;
106// 创建监视线程
107m_hThread = CreateThread( NULL, 0, ChangeMonitorThread,
108(LPVOID)this, CREATE_SUSPENDED, &m_dwThreadId );
109ASSERT( NULL != m_hThread );
110return TRUE;
111}
112
113void CChangeMonitor::EndMoniter( void )
114{
115// 判断线程是否存在
116if ( m_hThread )
117{
118// 判断线程是否结束
119DWORD dwExitCode;
120VERIFY( GetExitCodeThread( m_hThread, &dwExitCode ) );
121if ( STILL_ACTIVE == dwExitCode )
122{
123ASSERT( m_dwThreadId != 0 );
124// 向线程发送退出消息
125VERIFY( PostThreadMessage( m_dwThreadId, WM_MONITER_EXIT, 0, 0 ) );
126// 等待线程退出
127DWORD dwWaitResult = WaitForSingleObject( m_hThread, 500 );
128ASSERT( WAIT_FAILED != dwWaitResult );
129// 如果等待超时,强制结束线程
130if ( WAIT_TIMEOUT == dwWaitResult )
131{
132VERIFY( TerminateThread( m_hThread, 0 ) );
133TRACE_ERROR( -1 );
134}
135}
136// 关闭线程句柄,将线程相关数据置零
137VERIFY( CloseHandle( m_hThread ) );
138m_hThread = NULL;
139m_dwThreadId = 0;
140}
141m_hWnd = NULL;// 通知窗体置零
142}
143
144void CChangeMonitor::SendNotify( UINT nMsg )
145{
146// 检查通知窗体句柄是否存在
147ASSERT( m_hWnd != NULL );
148// 发送通知消息
149if ( FALSE == PostMessage( m_hWnd, nMsg, 0, 0 ) )
150{
151TRACE_ERROR( GetLastError() );
152}
153}
154
155DWORD CALLBACK ChangeMonitorThread( LPVOID pParam )
156{
157// 检查参数是否为空
158ASSERT( pParam != NULL );
159// 得到监视器类对象指针
160CChangeMonitor *pChaMon = (CChangeMonitor*)pParam;
161// 检查对象
162ASSERT( pChaMon->m_hThread != NULL );
163ASSERT( pChaMon->m_hWnd != NULL );
164ASSERT( pChaMon->m_dwThreadId != 0 );
165// 进入线程消息循环
166MSG msg;// 消息数据结构
167while( FALSE == PeekMessage( &msg, NULL, WM_MONITER_EXIT,
168WM_MONITER_EXIT, PM_REMOVE ) )
169{
170// 以0超时等待通知,直接返回等待结果
171DWORD dwWaitResult = pChaMon->WaitNotify();
172ASSERT( dwWaitResult != WAIT_FAILED );
173switch( dwWaitResult )// 处理等待结果
174{
175case WAIT_OBJECT_0:// 通知已接收
176// 向接收者发送通知消息
177pChaMon->SendNotify( WM_MONITER_FILE );
178// 继续下一次等待
179pChaMon->CallNextMoniter();
180break;
181case WAIT_TIMEOUT:
182break;
183}
184Sleep( 50 );
185}
186return 0;
187}
188
189
190// CDirectoryMonitor
191
192// 构造函数
193CDirectoryMonitor::CDirectoryMonitor( void )
194: m_hNotify( NULL )
195{
196}
197
198// 析构函数
199CDirectoryMonitor::~CDirectoryMonitor( void )
200{
201}
202
203// 启动监视
204BOOL CDirectoryMonitor::StartMoniter( HWND hWnd, LPCTSTR lpPath,
205 BOOL bSubTree, DWORD dwFilter )
206{
207// 调用父类同名函数
208if ( FALSE == CChangeMonitor::StartMoniter( hWnd ) )
209{
210return FALSE;
211}
212// 创建监视
213m_hNotify = FindFirstChangeNotification( lpPath, bSubTree, dwFilter );
214if ( INVALID_HANDLE_VALUE == m_hNotify )
215{
216m_hNotify = NULL;
217EndMoniter();
218TRACE_ERROR( GetLastError() );
219return FALSE;
220}
221// 启动监视线程
222VERIFY( ResumeThread( m_hThread ) );
223return TRUE;
224}
225
226void CDirectoryMonitor::EndMoniter( void )
227{
228// 调用父类同名函数
229CChangeMonitor::EndMoniter();
230// 判断通知句柄是否存在
231if ( m_hNotify )
232{
233// 结束通知
234VERIFY( FindCloseChangeNotification( m_hNotify ) );
235m_hNotify = NULL;// 通知句柄置零
236}
237}
238
239void CDirectoryMonitor::CallNextMoniter( void )
240{
241VERIFY( TRUE == FindNextChangeNotification( m_hNotify ) );
242}
243
244DWORD CDirectoryMonitor::WaitNotify( void )
245{
246return WaitForSingleObject( m_hNotify, 0 );
247}
248
249
250
251// CRegistryMonitor
252
253// 构造函数
254CRegistryMonitor::CRegistryMonitor( void )
255: m_hKey( NULL )
256, m_hNotify( NULL )
257, m_dwFilter( 0 )
258{
259}
260
261// 析构函数
262CRegistryMonitor::~CRegistryMonitor( void )
263{
264}
265
266// 启动监视
267BOOL CRegistryMonitor::StartMoniter( HWND hWnd, HKEY hRoot,
268LPCTSTR lpSubKey, DWORD dwFilter )
269{
270// 调用父类同名函数
271if ( FALSE == CChangeMonitor::StartMoniter( hWnd ) )
272{
273return FALSE;
274}
275// 成员数据赋值
276m_dwFilter = dwFilter;
277// 打开注册表键
278LONG lr;
279lr = RegOpenKeyEx( hRoot, lpSubKey, 0, KEY_NOTIFY, &m_hKey );
280if ( ERROR_SUCCESS != lr )
281{
282TRACE_ERROR( lr );
283return FALSE;
284}
285// 创建通知事件句柄
286m_hNotify = CreateEvent( NULL, FALSE, FALSE, NULL );
287ASSERT( m_hNotify == NULL );
288// 开始监视
289CallNextMoniter();
290// 启动监视线程
291VERIFY( ResumeThread( m_hThread ) );
292return TRUE;
293}
294
295// 结束监视
296void CRegistryMonitor::EndMoniter( void )
297{
298CChangeMonitor::EndMoniter();
299if ( m_hNotify )
300{
301VERIFY( CloseHandle( m_hNotify ) );
302m_hNotify = NULL;
303}
304if ( m_hKey )
305{
306VERIFY( ERROR_SUCCESS == RegCloseKey( m_hKey ) );
307m_hKey = NULL;
308}
309}
310
311void CRegistryMonitor::CallNextMoniter( void )
312{
313ASSERT( m_hKey != NULL );
314ASSERT( m_hNotify != NULL );
315// 创建监视句柄
316VERIFY( ERROR_SUCCESS == RegNotifyChangeKeyValue( m_hKey, TRUE,
317m_dwFilter, m_hNotify, TRUE ) );
318}
319
320DWORD CRegistryMonitor::WaitNotify( void )
321{
322return WaitForSingleObject( m_hNotify, 0 );
323}
324
2changenotify.h
3
4#pragma once
5
6#define WM_MONITER( WM_USER + 1000 )
7#define WM_MONITER_EXIT( WM_MONITER + 1 )
8#define WM_MONITER_FILE( WM_MONITER + 2 )
9
10#define ERROR_NOTIFY100000L
11#define ERROR_NOTIFY_ALREADY_START( ERROR_NOTIFY + 1 )
12
13
14DWORD CALLBACK ChangeMonitorThread( LPVOID pParam );
15class CChangeMonitor
16{
17public:
18CChangeMonitor();
19virtual ~CChangeMonitor();
20virtual BOOL StartMoniter( HWND hWnd );
21virtual void EndMoniter( void );
22protected:
23virtual void SendNotify( UINT nMsg );
24virtual void CallNextMoniter( void ) = 0;
25virtual DWORD WaitNotify( void ) = 0;
26protected:
27HANDLE m_hThread;
28HWND m_hWnd;
29DWORD m_dwThreadId;
30
31friend DWORD CALLBACK ChangeMonitorThread( LPVOID pParam );
32};
33
34
35
36class CDirectoryMonitor : public CChangeMonitor
37{
38public:
39CDirectoryMonitor();
40~CDirectoryMonitor();
41BOOL StartMoniter( HWND hWnd, LPCTSTR lpPath, BOOL bSubTree = TRUE,
42DWORD dwFilter = FILE_NOTIFY_CHANGE_LAST_WRITE );
43void EndMoniter( void );
44protected:
45virtual void CallNextMoniter( void );
46virtual DWORD WaitNotify( void );
47protected:
48HANDLE m_hNotify;
49};
50
51
52class CRegistryMonitor : public CChangeMonitor
53{
54public:
55CRegistryMonitor();
56~CRegistryMonitor();
57BOOL StartMoniter( HWND hWnd, HKEY hRoot, LPCTSTR lpSubKey,
58DWORD dwFilter = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET );
59void EndMoniter( void );
60protected:
61virtual void CallNextMoniter( void );
62virtual DWORD WaitNotify( void );
63protected:
64HANDLE m_hNotify;
65HKEY m_hKey;
66DWORD m_dwFilter;
67};
68
69
70
71
72//////////////////////////////////////////////////////
73changenotify.cpp
74
75#include "ChangeNotify.h"
76
77CChangeMonitor::CChangeMonitor( void )
78: m_hThread( NULL )
79, m_hWnd( NULL )
80, m_dwThreadId( 0 )
81{
82}
83
84CChangeMonitor::~CChangeMonitor( void )
85{
86EndMoniter();
87}
88
89BOOL CChangeMonitor::StartMoniter( HWND hWnd )
90{
91// 判断是否已经启动监视
92if ( NULL != m_hThread )
93{
94SetLastError( ERROR_NOTIFY_ALREADY_START );
95TRACE_ERROR( GetLastError() );
96return FALSE;
97}
98// 检查参数
99if ( NULL == hWnd )
100{
101SetLastError( ERROR_INVALID_PARAMETER );
102TRACE_ERROR( GetLastError() );
103return FALSE;
104}
105m_hWnd = hWnd;
106// 创建监视线程
107m_hThread = CreateThread( NULL, 0, ChangeMonitorThread,
108(LPVOID)this, CREATE_SUSPENDED, &m_dwThreadId );
109ASSERT( NULL != m_hThread );
110return TRUE;
111}
112
113void CChangeMonitor::EndMoniter( void )
114{
115// 判断线程是否存在
116if ( m_hThread )
117{
118// 判断线程是否结束
119DWORD dwExitCode;
120VERIFY( GetExitCodeThread( m_hThread, &dwExitCode ) );
121if ( STILL_ACTIVE == dwExitCode )
122{
123ASSERT( m_dwThreadId != 0 );
124// 向线程发送退出消息
125VERIFY( PostThreadMessage( m_dwThreadId, WM_MONITER_EXIT, 0, 0 ) );
126// 等待线程退出
127DWORD dwWaitResult = WaitForSingleObject( m_hThread, 500 );
128ASSERT( WAIT_FAILED != dwWaitResult );
129// 如果等待超时,强制结束线程
130if ( WAIT_TIMEOUT == dwWaitResult )
131{
132VERIFY( TerminateThread( m_hThread, 0 ) );
133TRACE_ERROR( -1 );
134}
135}
136// 关闭线程句柄,将线程相关数据置零
137VERIFY( CloseHandle( m_hThread ) );
138m_hThread = NULL;
139m_dwThreadId = 0;
140}
141m_hWnd = NULL;// 通知窗体置零
142}
143
144void CChangeMonitor::SendNotify( UINT nMsg )
145{
146// 检查通知窗体句柄是否存在
147ASSERT( m_hWnd != NULL );
148// 发送通知消息
149if ( FALSE == PostMessage( m_hWnd, nMsg, 0, 0 ) )
150{
151TRACE_ERROR( GetLastError() );
152}
153}
154
155DWORD CALLBACK ChangeMonitorThread( LPVOID pParam )
156{
157// 检查参数是否为空
158ASSERT( pParam != NULL );
159// 得到监视器类对象指针
160CChangeMonitor *pChaMon = (CChangeMonitor*)pParam;
161// 检查对象
162ASSERT( pChaMon->m_hThread != NULL );
163ASSERT( pChaMon->m_hWnd != NULL );
164ASSERT( pChaMon->m_dwThreadId != 0 );
165// 进入线程消息循环
166MSG msg;// 消息数据结构
167while( FALSE == PeekMessage( &msg, NULL, WM_MONITER_EXIT,
168WM_MONITER_EXIT, PM_REMOVE ) )
169{
170// 以0超时等待通知,直接返回等待结果
171DWORD dwWaitResult = pChaMon->WaitNotify();
172ASSERT( dwWaitResult != WAIT_FAILED );
173switch( dwWaitResult )// 处理等待结果
174{
175case WAIT_OBJECT_0:// 通知已接收
176// 向接收者发送通知消息
177pChaMon->SendNotify( WM_MONITER_FILE );
178// 继续下一次等待
179pChaMon->CallNextMoniter();
180break;
181case WAIT_TIMEOUT:
182break;
183}
184Sleep( 50 );
185}
186return 0;
187}
188
189
190// CDirectoryMonitor
191
192// 构造函数
193CDirectoryMonitor::CDirectoryMonitor( void )
194: m_hNotify( NULL )
195{
196}
197
198// 析构函数
199CDirectoryMonitor::~CDirectoryMonitor( void )
200{
201}
202
203// 启动监视
204BOOL CDirectoryMonitor::StartMoniter( HWND hWnd, LPCTSTR lpPath,
205 BOOL bSubTree, DWORD dwFilter )
206{
207// 调用父类同名函数
208if ( FALSE == CChangeMonitor::StartMoniter( hWnd ) )
209{
210return FALSE;
211}
212// 创建监视
213m_hNotify = FindFirstChangeNotification( lpPath, bSubTree, dwFilter );
214if ( INVALID_HANDLE_VALUE == m_hNotify )
215{
216m_hNotify = NULL;
217EndMoniter();
218TRACE_ERROR( GetLastError() );
219return FALSE;
220}
221// 启动监视线程
222VERIFY( ResumeThread( m_hThread ) );
223return TRUE;
224}
225
226void CDirectoryMonitor::EndMoniter( void )
227{
228// 调用父类同名函数
229CChangeMonitor::EndMoniter();
230// 判断通知句柄是否存在
231if ( m_hNotify )
232{
233// 结束通知
234VERIFY( FindCloseChangeNotification( m_hNotify ) );
235m_hNotify = NULL;// 通知句柄置零
236}
237}
238
239void CDirectoryMonitor::CallNextMoniter( void )
240{
241VERIFY( TRUE == FindNextChangeNotification( m_hNotify ) );
242}
243
244DWORD CDirectoryMonitor::WaitNotify( void )
245{
246return WaitForSingleObject( m_hNotify, 0 );
247}
248
249
250
251// CRegistryMonitor
252
253// 构造函数
254CRegistryMonitor::CRegistryMonitor( void )
255: m_hKey( NULL )
256, m_hNotify( NULL )
257, m_dwFilter( 0 )
258{
259}
260
261// 析构函数
262CRegistryMonitor::~CRegistryMonitor( void )
263{
264}
265
266// 启动监视
267BOOL CRegistryMonitor::StartMoniter( HWND hWnd, HKEY hRoot,
268LPCTSTR lpSubKey, DWORD dwFilter )
269{
270// 调用父类同名函数
271if ( FALSE == CChangeMonitor::StartMoniter( hWnd ) )
272{
273return FALSE;
274}
275// 成员数据赋值
276m_dwFilter = dwFilter;
277// 打开注册表键
278LONG lr;
279lr = RegOpenKeyEx( hRoot, lpSubKey, 0, KEY_NOTIFY, &m_hKey );
280if ( ERROR_SUCCESS != lr )
281{
282TRACE_ERROR( lr );
283return FALSE;
284}
285// 创建通知事件句柄
286m_hNotify = CreateEvent( NULL, FALSE, FALSE, NULL );
287ASSERT( m_hNotify == NULL );
288// 开始监视
289CallNextMoniter();
290// 启动监视线程
291VERIFY( ResumeThread( m_hThread ) );
292return TRUE;
293}
294
295// 结束监视
296void CRegistryMonitor::EndMoniter( void )
297{
298CChangeMonitor::EndMoniter();
299if ( m_hNotify )
300{
301VERIFY( CloseHandle( m_hNotify ) );
302m_hNotify = NULL;
303}
304if ( m_hKey )
305{
306VERIFY( ERROR_SUCCESS == RegCloseKey( m_hKey ) );
307m_hKey = NULL;
308}
309}
310
311void CRegistryMonitor::CallNextMoniter( void )
312{
313ASSERT( m_hKey != NULL );
314ASSERT( m_hNotify != NULL );
315// 创建监视句柄
316VERIFY( ERROR_SUCCESS == RegNotifyChangeKeyValue( m_hKey, TRUE,
317m_dwFilter, m_hNotify, TRUE ) );
318}
319
320DWORD CRegistryMonitor::WaitNotify( void )
321{
322return WaitForSingleObject( m_hNotify, 0 );
323}
324
监控目录用法:
首先监控者必须是一个窗体或控件,有句柄,能接受消息。
CDirectoryMonitor dm;
dm.StartMoniter( hWnd, _T("C:\\windows") );
在窗体中响应WM_MONITER_FILE消息就可以了
监控文件:
BOOL ReadDirectoryChangesW(
HANDLE hDirectory,
LPVOID lpBuffer,
DWORD nBufferLength,
BOOL bWatchSubtree,
DWORD dwNotifyFilter,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);