侦听Windows文件夹变更事件

简介:

通过以下两个类,可以实现对windows文件夹的事件侦听,包括新建文件,删除文件,文件重命名等事件;

FileSystemWather.cs

using System;
using System.Collections;
using System.IO;
using System.Threading;

namespace Whir.Software.FileCopy
{
    public delegate void Completed(string key);

    public class FileSystemWather
    {
        private readonly FileSystemWatcher _fsWather;

        private readonly Hashtable _hstbWather;

        /// <summary>
        ///     构造函数
        /// </summary>
        /// <param name="path">要监控的路径</param>
        /// <param name="filter">要监控的文件</param>
        /// <param name="includeSubdirectories">是否包含子文件夹</param>
        public FileSystemWather(string path, string filter, bool includeSubdirectories)
        {
            if (!Directory.Exists(path))
            {
                throw new Exception("找不到路径:" + path);
            }

            _hstbWather = new Hashtable();

            _fsWather = new FileSystemWatcher(path) {IncludeSubdirectories = includeSubdirectories, Filter = filter};
            _fsWather.Renamed += fsWather_Renamed;
            _fsWather.Changed += fsWather_Changed;
            _fsWather.Created += fsWather_Created;
            _fsWather.Deleted += fsWather_Deleted;
        }

        public event RenamedEventHandler OnRenamed;
        public event FileSystemEventHandler OnChanged;
        public event FileSystemEventHandler OnCreated;
        public event FileSystemEventHandler OnDeleted;

        /// <summary>
        ///     开始监控
        /// </summary>
        public void Start()
        {
            _fsWather.EnableRaisingEvents = true;
        }

        /// <summary>
        ///     停止监控
        /// </summary>
        public void Stop()
        {
            _fsWather.EnableRaisingEvents = false;
        }

        /// <summary>
        ///     filesystemWatcher 本身的事件通知处理过程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fsWather_Renamed(object sender, RenamedEventArgs e)
        {
            lock (_hstbWather)
            {
                if (!_hstbWather.ContainsKey(e.FullPath))
                {
                    _hstbWather.Add(e.FullPath, e);
                }
            }
            var watcherProcess = new WatcherProcess(sender, e);
            watcherProcess.OnRenamed += OnRenamed; //传递事件
            watcherProcess.OnCompleted += WatcherProcess_OnCompleted;
            var thread = new Thread(watcherProcess.Process);
            thread.Start();
        }


        private void fsWather_Created(object sender, FileSystemEventArgs e)
        {
            lock (_hstbWather)
            {
                if (!_hstbWather.ContainsKey(e.FullPath))
                {
                    _hstbWather.Add(e.FullPath, e);
                }
            }
            var watcherProcess = new WatcherProcess(sender, e);
            watcherProcess.OnCreated += OnCreated; //传递事件
            watcherProcess.OnCompleted += WatcherProcess_OnCompleted;
            var threadDeal = new Thread(watcherProcess.Process);
            threadDeal.Start();
        }

        private void fsWather_Deleted(object sender, FileSystemEventArgs e)
        {
            lock (_hstbWather)
            {
                if (!_hstbWather.ContainsKey(e.FullPath))
                {
                    _hstbWather.Add(e.FullPath, e);
                }
            }
            var watcherProcess = new WatcherProcess(sender, e);
            watcherProcess.OnDeleted += OnDeleted; //传递事件
            watcherProcess.OnCompleted += WatcherProcess_OnCompleted;
            var tdDeal = new Thread(watcherProcess.Process);
            tdDeal.Start();
        }

        private void fsWather_Changed(object sender, FileSystemEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Changed)
            {
                if (_hstbWather.ContainsKey(e.FullPath))
                {
                    WatcherChangeTypes oldType = ((FileSystemEventArgs) _hstbWather[e.FullPath]).ChangeType;
                    if (oldType == WatcherChangeTypes.Created || oldType == WatcherChangeTypes.Changed)
                    {
                        return;
                    }
                }
            }

            lock (_hstbWather)
            {
                if (!_hstbWather.ContainsKey(e.FullPath))
                {
                    _hstbWather.Add(e.FullPath, e);
                }
            }
            var watcherProcess = new WatcherProcess(sender, e);
            watcherProcess.OnChanged += OnChanged; //传递事件
            watcherProcess.OnCompleted += WatcherProcess_OnCompleted;
            var thread = new Thread(watcherProcess.Process);
            thread.Start();
        }

        /// <summary>
        ///     使用了线程安全的Hashtable来处理一次改变触发两次事件的问题,
        ///     要注意的是在实际项目使用中,在通过监控文件事情触发时开一个线程WatcherProcess去处理自己业务逻辑的时候,
        ///     不管业务逻辑成功或者失败(例如有异常抛出一定要try一下)一定要让WatcherProcess的Completed
        ///     也就是MyFileSystemWather的WatcherProcess_OnCompleted执行去移除对应变化文件的Hashtable的key,
        ///     不然下次此文件改变时是无法触发你的业务逻辑的。
        /// </summary>
        /// <param name="key"></param>
        public void WatcherProcess_OnCompleted(string key)
        {
            lock (_hstbWather)
            {
                _hstbWather.Remove(key);
            }
        }
    }
}
WatcherProcess.cs
using System.IO;

namespace Whir.Software.FileCopy
{
    public class WatcherProcess
    {
        private readonly object _eParam;
        private readonly object _sender;

        public WatcherProcess(object sender, object eParam)
        {
            _sender = sender;
            _eParam = eParam;
        }

        public event RenamedEventHandler OnRenamed;
        public event FileSystemEventHandler OnChanged;
        public event FileSystemEventHandler OnCreated;
        public event FileSystemEventHandler OnDeleted;
        public event Completed OnCompleted;

        public void Process()
        {
            if (_eParam.GetType() == typeof (RenamedEventArgs))
            {
                OnRenamed(_sender, (RenamedEventArgs) _eParam);
                OnCompleted(((RenamedEventArgs) _eParam).FullPath);
            }
            else
            {
                var e = (FileSystemEventArgs) _eParam;
                if (e.ChangeType == WatcherChangeTypes.Created)
                {
                    OnCreated(_sender, e);
                    OnCompleted(e.FullPath);
                }
                else if (e.ChangeType == WatcherChangeTypes.Changed)
                {
                    OnChanged(_sender, e);
                    OnCompleted(e.FullPath);
                }
                else if (e.ChangeType == WatcherChangeTypes.Deleted)
                {
                    OnDeleted(_sender, e);
                    OnCompleted(e.FullPath);
                }
                else
                {
                    OnCompleted(e.FullPath);
                }
            }
        }
    }
}
使用方法:

var wather = new FileSystemWather(TxtFrom.Text, "*.*", true);
            wather.OnChanged += OnChanged;
            wather.OnCreated += OnCreated;
            wather.OnRenamed += OnRenamed;
            wather.OnDeleted += OnDeleted;
            wather.Start();
对应事件响应:

        private void OnCreated(object source, FileSystemEventArgs e)
        {
            //文件全路径:e.FullPath
            //文件名:e.Name
            //事件类型: e.ChangeType
            //自定义逻辑处理
        }
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            //自定义逻辑处理
        }
        private void OnDeleted(object source, FileSystemEventArgs e)
        {
            //自定义逻辑处理
        }
        private void OnRenamed(object source, RenamedEventArgs e)
        {
            //自定义逻辑处理
        }


目录
相关文章
|
消息中间件 安全 API
C#实现操作Windows窗口句柄:SendMessage/PostMessage发送系统消息、事件和数据【窗口句柄总结之二】
SendMessage/PostMessage API 可以实现发送系统消息,这些消息可以定义为常见的鼠标或键盘事件、数据的发送等各种系统操作......
5880 1
C#实现操作Windows窗口句柄:SendMessage/PostMessage发送系统消息、事件和数据【窗口句柄总结之二】
|
22天前
|
缓存 安全 网络协议
使用事件日志识别常见 Windows 错误
事件查看器是Windows操作系统中的标准诊断工具,用于记录系统事件,包括硬件问题、软件中断和系统行为等详细信息。通过分析这些日志,管理员能够追踪和解决系统错误。访问方法包括使用快捷键Win + R输入eventvwr.msc,或通过控制面板进入。事件查看器中的每条记录包含事件ID、来源和描述,帮助识别和解决问题。常见错误如蓝屏死机、DLL错误、驱动程序错误等,可通过更新驱动程序、运行系统诊断、使用恢复功能等方式解决。
|
4月前
|
Linux Windows
Windows系统批量创建文件夹的技巧
Windows系统批量创建文件夹的技巧
127 1
|
4月前
|
Windows
windows 文件夹视图全局生效
【8月更文挑战第31天】在 Windows 中,要使文件夹视图设置全局生效,请先在一个文件夹中设置视图模式和排序方式等,然后点击“查看”选项卡中的“选项”按钮,打开“文件夹选项”,切换到“查看”选项卡,点击“应用到文件夹”按钮以确认设置。这样,大多数文件夹将采用相同视图。不过,部分特殊文件夹可能不遵循此设置。
|
5月前
|
Windows
windows 文件夹视图全局生效
【8月更文挑战第20天】在Windows中实现文件夹视图全局设置:首先调整任一文件夹的视图样式,如选择“大图标”或“详细信息”。接着设置排序和分组选项。随后,在该文件夹的“查看”选项卡中点击“选项”,在“文件夹选项”的“查看”标签下点击“应用到文件夹”。确认后,所有文件夹将采用相同视图。注意:特定文件夹可能不受此设置影响。
|
5月前
|
开发框架 .NET API
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
181 0
|
8月前
|
存储 安全 搜索推荐
Windows之隐藏特殊文件夹(自定义快捷桌面程序)
Windows之隐藏特殊文件夹(自定义快捷桌面程序)
122 1
|
7月前
|
Windows
windows系统vbs脚本 提取文件夹中的所有文件名
windows系统vbs脚本 提取文件夹中的所有文件名
51 0
|
8月前
|
Windows
Windows下文件夹映射的实现(将文件夹从一个盘映射到另一个盘)
Windows下文件夹映射的实现(将文件夹从一个盘映射到另一个盘)
602 0
|
Shell C++ Python
VScode 右键菜单加入使用用VSCode打开文件和文件夹【Windows】
鼠标右击文件或者文件夹,可直接用VSCode打开,非常方便。但如果我们在安装VSCode的时候没有勾选这2个选项,那就享受不到这个便捷的功能了,那么怎么办呢?此时存在2种方法进行修复:重装软件在安装的过程中勾选上这2个选项即可(肯定我们不愿意,很多配置和插件都用习惯了,再装很费事,即使是 setting sync 也免不了麻烦,尤其是配置了python或C/C++的开发环境,所以这个我们不推荐)安装勾选修改注册表右键打开文件右键打开文件夹。
495 0