0%

Dir Monitor

目录监视功能

这个实现的效果有很多办法,比如说Hook,但是这个的话呢相对而言有点小麻烦,但是灵活性比较好,但当我们要求比较低,只是想单纯的监视的时候(对更改的内容和文件名之类不感兴趣的时候),我们可以考虑FindFirstChangeNotification这个相关的函数。

FindFirstChangeNotification

这个函数是队目录监控的一个函数,具体微软怎么实现的不知道(感觉应该也跟钩子有关系),这个函数调用比较简单,共有下面三个参数:

1
2
3
4
5
6
HANDLE FindFirstChangeNotification(
LPCTSTR lpPathName, // pointer to name of directory to watch
BOOL bWatchSubtree, // flag for monitoring directory or
// directory tree
DWORD dwNotifyFilter // filter conditions to watch for
);
  1. lpPathName:监视的目录文件夹
  2. bWatchSubtree :是否监视子目录
  3. dwNotifyFilter:监视的类型
  • 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_SECURITY
    看名字就能看明白了。
    返回值是一个句柄,这个句柄可以通过等待进行相应,这也就是下面我将要说到的一个函数。和这个相关的是:FindNextChangeNotification, FindCloseChangeNotification这个在最后提。

    WaitForMultipleObjects

    这个函数有点类似于:WaitForSingleObject,但是这个我们是支持单个对象的,但对于多对象的我们就需要用到WaitForMultipleObjects,看下MSDN给出的定义:
    1
    2
    3
    4
    5
    DWORD WaitForMultipleObjects(
    DWORD nCount, // number of handles in the handle array
    CONST HANDLE *lpHandles, // pointer to the object-handle array
    BOOL fWaitAll, // wait flag
    DWORD dwMilliseconds // time-out interval in milliseconds);
  1. nCount:等待的个数
  2. lpHandles:等待时间句柄的数组
  3. fWaitAll:是否等待所有时间都相应
  4. dwMilliseconds:等待的时间

dwMilliseconds这个参数如果我们提供:INFINITE 这个的话呢将视为无线等待(一般就填写这个就比较好)。
返回值:
WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount – 1):If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled.
If bWaitAll is FALSE, the return value minus WAIT_OBJECT_0 indicates the lpHandles array index of the object that satisfied the wait. If more than one object became signalled during the call, this is the array index of the signalled object with the smallest index value of all the signalled objects.

WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount – 1):If bWaitAll is TRUE, the return value indicates that the state of all specified objects is signaled and at least one of the objects is an abandoned mutex object.
If bWaitAll is FALSE, the return value minus WAIT_ABANDONED_0 indicates the lpHandles array index of an abandoned mutex object that satisfied the wait.

WAIT_TIMEOUT:The time-out interval elapsed and the conditions specified by the bWaitAll parameter are not satisfied.

是不是有点眼花缭乱,我翻译一下吧:

如果bWaitAll为真,则返回值表示所有指定对象的状态都有信号。如果bWaitAll为FALSE,则返回值减去WAIT_OBJECT_0表示满足等待的对象的lpHandles数组索引。如果在调用期间有多个对象被标记,这是标记对象的数组索引,索引值是所有标记对象的最小值。如果bWaitAll为真,则返回值表明所有指定对象的状态都有信号,并且至少有一个对象是废弃的互斥对象。如果bWaitAll为FALSE,则返回值减去wait_oned_0表示满足等待的废弃互斥对象的lpHandles数组索引。超时时间间隔和bWaitAll参数指定的条件不满足。

简单地说我们如果是无限等待返回给我们的值-WAIT_OBJECT_0就是我们提供的对象句柄的数组的下标值。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
HANDLE m_charnge[3];
m_charnge[0]=FindFirstChangeNotification("E:\\",TRUE,FILE_NOTIFY_CHANGE_FILE_NAME);
m_charnge[1]=FindFirstChangeNotification("E:\\",TRUE,FILE_NOTIFY_CHANGE_DIR_NAME);
m_charnge[2]=FindFirstChangeNotification("E:\\",TRUE,FILE_NOTIFY_CHANGE_LAST_WRITE);
while(true)
{
DWORD Rv = WaitForMultipleObjects(3,m_charnge,FALSE,INFINITE);
switch(Rv-WAIT_OBJECT_0)
{
case 0:
cout<<"文件名改變"<<endl;
case 1:
cout<<"目錄改變"<<endl;
case 2:
cout<<"內容改變"<<endl;
}
FindNextChangeNotification(m_charnge[Rv]);
}
return 0;
}

注意的是在填写监视目录的时候别忘记转义,其他的都好说。