通过以下两个类,可以实现对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)
{
//自定义逻辑处理
}