Windows编程:文件监控

发布时间 2023-05-31 17:21:31作者: zhaotianff

最近在做虚拟打印机时,需要实时监控打印文件的到达,并移动文件到另外的位置。一开始我使用了线程,在线程里去检测新文件的到达。实际上Windows提供了一个文件监控接口函数ReadDIrectoryChangesW。这个函数可以对所有文件操作进行监控。

 

ReadDirectoryChangesW

函数声明

 1 BOOL ReadDirectoryChangesW(
 2   [in]                HANDLE                          hDirectory,
 3   [out]               LPVOID                          lpBuffer,
 4   [in]                DWORD                           nBufferLength,
 5   [in]                BOOL                            bWatchSubtree,
 6   [in]                DWORD                           dwNotifyFilter,
 7   [out, optional]     LPDWORD                         lpBytesReturned,
 8   [in, out, optional] LPOVERLAPPED                    lpOverlapped,
 9   [in, optional]      LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
10 );

 

参数

hDirectory

指向要监听的目录句柄,必须使用FILE_LIST_DIRECTORY访问权限打开此目录。

 

lpBuffer

指向要读取DWORD对齐结果的格式化缓冲区的指针。该缓冲区的结构由FILE_NOTIFY_INFORMATION结构定义

 

nBufferLength

lpBuffer参数指向的缓冲区大小

 

bWatchSubtree

 指示是否以指定目录为根目录进行监控。

True:监视以指定目录为根的目录树

FALSE:仅监视指定目录

 

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_LAST_ACCESS 监视目录或子树中文件最后访问时间的任何更改
FILE_NOTIFY_CHANGE_CREATION 监视目录或子树中文件创建时间的任何更改
FILE_NOTIFY_CHANGE_SECURITY 监视目录或子树中任何安全描述符更改

 

lpBytesReturned

对于同步调用,此参数接收传输到lpBuffer参数中的字节数

 

lpOverlapped

指向OVERLAPPED结构的指针,提供在异步操作期间要用的数据,否则该值为NULL

 

lpConpletionRoutine

指向完成例程的指针,当操作已经完成或取消,并且调用线程处于可警告的等待状态时才会调用它

 

返回值

成功:不为0

失败:0

 

监控指定目录下的文件创建

假设我这里要监控D:\PrintFiles目录下的文件更改,操作如下:

打开目录,获取文件句柄

1     // 打开目录, 获取文件句柄
2     HANDLE hDirectory = ::CreateFile(L"D:\\PrintFiles", FILE_LIST_DIRECTORY,
3         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
4         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5     if (INVALID_HANDLE_VALUE == hDirectory)
6     {
7         return 0;
8     }

 

调用ReadDirectoryChangesW监控文件夹

我这里只演示同步调用,异步调用可以参考MSDN文档。同步调用时,如果监控的目录未发生更改,会一直阻塞在那里。

 

 

 

参考资料:

https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw?redirectedfrom=MSDN