监控Windows文件夹下面的文件(C#和C++实现)

最近在做虚拟打印机时,需要实时监控打印文件的到达,并移动文件到另外的位置。一开始我使用了线程,在线程里去检测新文件的到达。实际上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目录下的文件更改,操作如下:

打开目录,获取文件句柄

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

调用ReadDirectoryChangesW监控文件夹

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

      DWORD dwRet = 0;DWORD dwBufferSize = 2048;BYTE* pBuf = new BYTE[dwBufferSize];FILE_NOTIFY_INFORMATION* pFileNotifyInfo = (FILE_NOTIFY_INFORMATION*)pBuf;BOOL 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){DWORD dwError = GetLastError();std::cout << "ReadDirectoryChangesW failed - " << dwError << std::endl;}std::wcout.imbue(std::locale("chs"));//判断操作类型switch (pFileNotifyInfo->Action){case FILE_ACTION_ADDED:std::wcout << "Create file " << pFileNotifyInfo->FileName << std::endl;break;default:break;}CloseHandle(hDirectory);delete[] pBuf;

运行效果

System.IO.FileSystemWatcher类

在C#中,可以使用 System.IO.FileSystemWatcher类来进行监听。它内部也是调用了ReadDirectoryChangesW API函数

监控文件的行为定义在System.IO.NotifyFilters

 1    [Flags]2     public enum NotifyFilters3     {4         FileName = 0x1,5         DirectoryName = 0x2,6         Attributes = 0x4,7         Size = 0x8,8         LastWrite = 0x10,9         LastAccess = 0x20,
10         CreationTime = 0x40,
11         Security = 0x100
12     }

在C#中是通过事件订阅的形式来进行通知的。

C#进行了再次封装,所以会比直接在C++中使用要方便一些。创建监听后,只需要等待事件触发就行了。

FileSystemWatcher使用方法如下:

              FileSystemWatcher systemWatcher = new FileSystemWatcher();systemWatcher.Path = this.textBox1.Text;//设置监听的行为//这里设置为文件名systemWatcher.NotifyFilter = NotifyFilters.FileName;//设置文件类型过滤systemWatcher.Filter = "*.txt";systemWatcher.Changed += (obj, args) => { ShowMsg($"文件更改{args.Name}"); };systemWatcher.Created += (obj, args) => { ShowMsg($"文件创建{args.Name}"); };systemWatcher.Deleted += (obj, args) => { ShowMsg($"文件删除{args.Name}"); };systemWatcher.Renamed += (obj, args) => { ShowMsg($"文件重命名{args.Name}"); };//开始监听systemWatcher.EnableRaisingEvents = true;    

运行效果

示例代码

参考资料:

ReadDirectoryChangesW function (winbase.h) - Win32 apps | Microsoft Learn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/50183.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SAP中生产版本维护

流程概述 本流程为生产版本主数据维护流程,当PBOM、工艺路线主数据维护完成后,方能进行此流程。由于S/4HANA系统中,生产版本被定义为BOM展开的必要条件,因此所有工厂都必须在运行物料需求计划与生产执行等流程前将生产版本维护完成,与此同时,生产版本数据还是财务模块发…

【C语言】数组栈的实现

栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&#…

学习大数据DAY24 Shell脚本的书写

目录 shell 的变量 系统变量 特殊变量 运算符 if 选择结构 ---then 独立一行 case 语句 等值判断 上机练习 10 附加题 for 循环 while 循环 乘法表(双层嵌套) 上机练习 11 把附加题代码修改为循环形式 shell 的变量 系统变量 $HOME : 当前登录用户的 " 家…

套接字选项、广播和组播

1. 套接字选项(socket options) 每一个套接字(socket)在不同的协议层次(级别)上面有不同的行为属性(选项) 我们可以设置 / 获取指定的套接字选项 getsockopt&#xff1a;获取套接字的选项 setsockopt&#xff1a;设置套接字的选项 NAMEgetsockopt, setsockopt - get and set op…

python自动化运维 通过paramiko库和time库实现服务器自动化管理

目录 一.前言 二. 代码实现以及解析 2.1导入必要的库 2.2定义服务器信息 2.3创建 SSH 客户端连接函数 2.4执行远程命令函数 2.5获取系统信息函数 2.6重启服务函数 2.7 主函数 三.致谢 一.前言 在数字化时代&#xff0c;IT 基础设施的规模和复杂性不断增长&am…

Hadoop集群安装配置

文章目录 Hadoop部署配置集群配置历史服务器配置日志的聚集分发Hadoop群起集群Hadoop群起脚本 准备工作&#xff1a;需要3台虚拟机&#xff0c;每台虚拟机搭建好JDK并配置环境变量 Hadoop部署 1&#xff09;集群部署规划 注意&#xff1a;NameNode和SecondaryNameNode不要安…

批处理操作系统、分时操作系统、实时操作系统

批处理操作系统&#xff1a; 特点&#xff1a;批处理操作系统主要用于处理一系列作业。作业是把程序、数据连同作业说明书组织起来的任务单位&#xff0c;这些作业被组织成批作业。系统将这些作业按顺序执行&#xff0c;用户在提交作业后通常不需要等待作业完成&#xff0c;而是…

Hadoop NameNode 进入 Safe Mode 的问题分析与解决方案

随着大数据技术的不断发展&#xff0c;Hadoop 已经成为了处理海量数据不可或缺的一部分。然而&#xff0c;在使用 Hadoop 的过程中&#xff0c;我们经常会遇到 NameNode 进入 Safe Mode 的情况&#xff0c;这可能会导致集群暂时无法进行数据写入操作。本文将详细介绍 NameNode …

Java OpenCV 图像处理40 图形图像 图片裁切ROI

Java OpenCV 图像处理40 图形图像 图片裁切 在 OpenCV 中&#xff0c;Rect 类是用来表示矩形的数据结构&#xff0c;通常用于定义图像处理中的感兴趣区域&#xff08;Region of Interest&#xff0c;ROI&#xff09;&#xff0c;或者指定图像中的某个区域的位置和大小。Rect 类…

使用Apache SeaTunnel进行二次开发的实践分享

大家好&#xff0c;我是范佳&#xff0c;是Apache SeaTunnel社区的PMC member。今天给大家分享一些基于Apache SeaTunnel二次开发的内容。 这部分内容主要涉及代码层面的知识&#xff0c;如果大家有什么疑问&#xff0c;欢迎来社区找我交流&#xff01; 引言 大部分数据开发工…

如何使用 API list 极狐GitLab 容器镜像仓库中的 tag?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…

【Pytorch实战教程】内存泄漏以及Pytorch中内存泄露的注意事项

文章目录 内存泄漏的原因内存泄漏的影响在不同编程语言中的内存泄漏在PyTorch中的内存泄漏示例总结内存泄漏是指在计算机 程序运行过程中, 动态分配的 内存由于某些原因 没有被释放或回收,导致这些内存块 无法再被使用或重新分配。 内存泄漏会导致程序占用越来越多的内存…

【微信小程序实战教程】之微信小程序 WXML 语法详解

WXML语法基础 从本章开始&#xff0c;我们就正式进入到了小程序项目开发学习的初级阶段&#xff0c;本章将介绍小程序的界面构成。有过网页开发学习经历的同学都知道&#xff0c;网页开发所使用的技术是HTML、CSS和JS&#xff0c;其中HTML用于描述整个网页的结构&#xff0c;也…

第三十一天 chrome调试工具

打开调试工具 页面空白处右击 检查 或者F12 使用调试工具 ctrl滚轮改变代码大小 左边是html 右边是css css可以直接改动数值左右箭头或者直接输入 查看颜色 ctrl0 复原浏览器大小 点击元素右侧出现样式引入 没有的话 说明类名或者样式引用错误 这里的.new-left是存在的 如果类…

四步实现网站HTTPS访问

随着网络安全的重要性日益凸显&#xff0c;HTTPS&#xff08;超文本传输安全协议&#xff09;已成为现代网站的标准配置。HTTPS协议作为HTTP协议的安全版本&#xff0c;通过SSL协议加密数据传输&#xff0c;不仅能保护用户数据的安全&#xff0c;还能提升搜索引擎排名&#xff…

已经安装了pycryptodome,但是导入的时候始终报错:ModuleNotFoundError: No module named “Crypto”

嗨&#xff0c;我是兰若&#xff0c;如果你在安装pycryptodome时&#xff0c;始终安装不上&#xff0c;那么你一定要看这篇文章&#xff0c;大部分的小伙伴是已经安装了 pycryptodome&#xff0c;但仍然无法导入&#xff0c;可能有几个原因。以下是一些常见的解决方案&#xff…

重塑互联网生态:探索Web 3.0、大数据与隐私保护的新篇章

引言&#xff1a;互联网的新纪元 随着互联网技术的日新月异&#xff0c;我们正迈入一个全新的时代&#xff0c;其中Web 3.0、大数据以及隐私保护成为塑造未来互联网生态的三大核心力量。它们不仅改变了我们与互联网交互的方式&#xff0c;更深刻地影响着社会的方方面面。 Web…

linux之shell脚本实战

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

docker 构建 mongodb

最近需要在虚拟机上构建搭建mongo的docker容器&#xff0c;搞了半天老有错&#xff0c;归其原因&#xff0c;是因为现在最新的mango镜像的启动方式发生了变化&#xff0c;故此现在好多帖子&#xff0c;就是错的。 ok&#xff0c;话不多说&#xff1a; # 拉取最新镜像&#xf…

华为云依赖引入错误

问题&#xff1a;记录一次项目加在华为云依赖错误&#xff0c;如下&#xff1a; 错误信息&#xff1a;Could not find artifact com.huawei.storage:esdk-obs-java:pom:3.1.2.1 in bintray-qcloud-maven-repo (https://dl.bintray.com/qcloud/maven-repo/) 找到本地仓库&#…