使用 ReadDirecotryChangesW 函数实现文件监控
背景
在我没有了解 ReadDirecotryChangesW 这个目录监控函数之前,一直认为要想实现计算机上的文件监控,能够监控计算机上每个文件的改动,是一件极其困难的事情,曾经自己也细想过,但都没有什么好的思绪。不过,事实上,文件监控的确是一件比较复杂的事情。好在Windows为我们提供了一个功能强大,但是使用较为方便的函数接口,这边是我们这篇文章要讲解的 ReadDirecotryChangesW 函数。
函数介绍
// 检索描述指定目录中更改的信息,但不会报告对指定目录本身的更改。
// 如果函数成功,则返回值不为零。 对于同步调用,这意味着操作成功。 对于异步调用,这表示操作成功排队。
BOOL WINAPI ReadDirectoryChangesW(
_In_ HANDLE hDirectory, // 要监视的目录的句柄。必须使用FILE_LIST_DIRECTORY访问权限打开此目录。
_Out_ LPVOID lpBuffer, // 指向要读取结果的DWORD对齐的格式化缓冲区的指针
_In_ DWORD nBufferLength, // lpBuffer参数指向的缓冲区的大小
_In_ BOOL bWatchSubtree, // 是否监视以指定目录为根的目录树
_In_ DWORD dwNotifyFilter, // 函数检查以确定等待操作是否已满足过滤条件
_Out_opt_ LPDWORD lpBytesReturned, // 接收传输到lpBuffer参数的字节数
_Inout_opt_ LPOVERLAPPED lpOverlapped, // 指向OVERLAPPED结构的指针,提供在异步操作期间要使用的数据
_In_opt_ LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // 指向完成例程的指针
);
实现过程
(1)打开目录,获取文件句柄
首先,我们需要根据目录路径,调用 CreateFile 函数来打开目录,获取文件句柄,因为下面的调用的 ReadDirecotryChangesW 函数需要用到这个文件句柄。根据上面函数介绍,文件句柄必须要有 FILE_LIST_DIRECTORY 权限,所以要创建 FILE_LIST_DIRECTORY 权限的文件句柄。而且,要获取目录的句柄,需要以 FILE_FLAG_BACKUP_SEMANTICS 为标志调用 CreateFile 函数。
(2)设置目录监控
然后,我们可以调用 ReadDirecotryChangesW 函数设置目录监控。其中,第 1 个参数表示监控目录句柄;第 2 个参数表示输出缓冲区;第 3 个参数表示输出缓冲区大小;第 4 个参数表示是否监控指定目录下的文件及其子目录下的文件,TRUE,则监控,FALSE则表示只监控指定目录下的文件;第 5 个参数表示操作过滤,本文只监控文件名更改、属性更改以及最后一次写入更改操作;第 6 个参数表示返回缓冲区的字节数;第 7 、第 8 个参数为NULL。
(3)判断文件操作类型并将宽字节文件名字符串转成多字节字符串表示
只要有满足设置条件的文件操作,ReadDirectoryChangesW 立马返回信息,并将返回的信息返回到输出缓冲区中,返回数据是按 FILE_NOTIFY_INFORMATION 结构返回的,所以,我们直接按照 FILE_NOTIFY_INFORMATION 结构解析数据。在 FILE_NOTIFY_INFORMATION 结构中,4字节整型变量 Action 表示操作类型,宽字节字符串变量 FileName 表示更改文件的文件名。获取了一个文件操作之后,还要继续循环设置。如此,才能获取下一个文件操作。
编码实现
// 宽字节字符串转多字节字符串
void W2C(wchar_t *pwszSrc, int iSrcLen, char *pszDest, int iDestLen)
{
::RtlZeroMemory(pszDest, iDestLen);
// 宽字节字符串转多字节字符串
::WideCharToMultiByte(CP_ACP,
0,
pwszSrc,
(iSrcLen / 2),
pszDest,
iDestLen,
NULL,
NULL);
}
// 目录监控多线程
UINT MonitorFileThreadProc(LPVOID lpVoid)
{
char *pszDirectory = (char *)lpVoid;
// 打开目录, 获取文件句柄
HANDLE hDirectory = ::CreateFile(pszDirectory, FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE == hDirectory)
{
ShowError("CreateFile");
return 1;
}
char szTemp[MAX_PATH] = { 0 };
BOOL bRet = FALSE;
DWORD dwRet = 0;
DWORD dwBufferSize = 2048;
// 申请一个足够大的缓冲区
BYTE *pBuf = new BYTE[dwBufferSize];
if (NULL == pBuf)
{
ShowError("new");
return 2;
}
FILE_NOTIFY_INFORMATION *pFileNotifyInfo = (FILE_NOTIFY_INFORMATION *)pBuf;
// 开始循环设置监控
do
{
::RtlZeroMemory(pFileNotifyInfo, dwBufferSize);
// 设置监控目录
bRet = ::ReadDirectoryChangesW(hDirectory,
pFileNotifyInfo,
dwBufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_LAST_WRITE,
&dwRet,
NULL,
NULL);
if (FALSE == bRet)
{
ShowError("ReadDirectoryChangesW");
break;
}
// 将宽字符转换成窄字符
W2C((wchar_t *)(&pFileNotifyInfo->FileName), pFileNotifyInfo->FileNameLength, szTemp, MAX_PATH);
// 判断操作类型并显示
switch (pFileNotifyInfo->Action)
{
case FILE_ACTION_ADDED:
{
// 新增文件
printf("[File Added Action]%s\n", szTemp);
break;
}
default:
{
break;
}
}
} while (bRet);
// 关闭句柄, 释放内存
::CloseHandle(hDirectory);
delete[] pBuf;
pBuf = NULL;
return 0;
}
测试
现在,根据上面的实现原理,我们将开发好的程序直接运行。本文的例子,是监控”C:\Users\DemonGan\Desktop\temp\“目录的文件增加情况。所以,我们复制一个文件到在此目录下,程序成功实时显示目录中的变化信息:
相关文章
- 用了这款docker监控平台,再也不用记一大堆命令了,真香
- Python监控Windows下的文件变化
- oracle 数据库监控修改文件配置
- 监控命令之tsar
- Python 监控文件移动解压
- 如何监控 NGINX(第一篇)
- Linux利用curl监控api接口,请求失败,发送报警邮件
- Weblogic 监控工具汇总及简介
- Linux下用Mytop监控MySQL资源
- 四、Python3自动化运维——业务监控之文件对比
- Linux - ps aux ,more,less,head,tail,head和tail的高级用法,使用tail 动态监控某个文件的变化
- 低照度监控前景广阔 企业展开激烈角逐
- Qt编写视频监控系统70-OSD标签和图形信息(支持写入到文件)
- Qt编写安防视频监控系统20-录像机管理
- dm 数据库安装和维护 和dem 监控
- Flink监控:Monitoring Apache Flink Applications
- Linux-001-nmon系统性能监控工具的使用及报表产出
- 不仅是新零售 溯源和监控也是RFID技术精彩应用领域
- 僵尸网络再次来袭急剧膨胀 监控设备安全告急
- 浅析PM2的十个实用功能:自动保存、自定义日志文件、设置内存限制、查看进程信息详细、监控所有进程、使用SourceMap定位错误位置、监听目录文件变化自动重启、4种失败重启策略(零延迟高可用)、命名空间对服务归类、内置http服务器
- 网络监控四大技术趋势 平台将朝大集成方向发展
- pyinotify asyncio监控文件和文件夹变化
- Java系统开发中进行全局异常管理,对参数异常、请求异常、媒体异常、数据库异常、文件异常、JSON异常、运行时异常等等进行分类处理,可以对异常进行监控并记录,减少代码冗余和重复工作量,让用户界面更友好
- 非常易用的网络路径中的网络延迟测试和监控以及自动发送报告工具
- Splunk虚拟化监控系统能为企业做什么?