好多时候,我们都需要知道某些目录下的文件什么时候被修改、删除过等,如果能用miniFilter驱动过滤来做的话当然是最好不过了,这是内核级别的,当然也比较复杂。如果只是简单的记录就没必要用驱动过滤级别的来做了,用FileSystemWatcher来做就要简单得多。
FileSystemWatcher组件可以监视文件系统,并在文件系统发生改变时作出反应。FileSystemWatcher 常用于文件系统变更的监控,当被监视的文件夹目录被创建、修改、重命名或删除时,会触发以下事件:
1.Created: 当新建文件或者文件夹
2.Changed:当文件或者文件夹已经完成修改
3.Renamed:当文件或者文件夹完成重命名
4.Deleted:当文件或者文件夹被删除
5.Error:当变更过程发生错误
下面我们一起来完成一个文件监控实例。
一、实例化FileSystemWatcher类,并注册监听事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | //创建一个FileSystemWatcher,并设置其属性 FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); //设置监控的路径 fileSystemWatcher.Path = “监控路径”; //是否监控指定路径中的子目录 fileSystemWatcher.IncludeSubdirectories = true ; //启用 fileSystemWatcher.EnableRaisingEvents = true ; //注册监听事件,Created、Changed、Deleted三个事件传递的参数是一样的,我们就用同一个方法来处理就可以了 fileSystemWatcher.Changed += new FileSystemEventHandler(FileSystemWatcher_EventHandler); fileSystemWatcher.Created += new FileSystemEventHandler(FileSystemWatcher_EventHandler); fileSystemWatcher.Deleted += new FileSystemEventHandler(FileSystemWatcher_EventHandler); fileSystemWatcher.Renamed += new RenamedEventHandler(FileSystemWatcher_Renamed); fileSystemWatcher.Error += new ErrorEventHandler(FileSystemWatcher_Error); |
二、事件处理
FileSystemEventArgs 对象成员有:Name、OldName、ChangeType、FullPath、OldFullPath等,看名就明白是什么了,这里不做过多解释。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | //创建一个FileSystemWatcher,并设置其属性 FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); //设置监控的路径 fileSystemWatcher.Path = “监控路径”; //是否监控指定路径中的子目录 fileSystemWatcher.IncludeSubdirectories = true ; //启用 fileSystemWatcher.EnableRaisingEvents = true ; //Created、Changed、Deleted三个事件的处理方法 private static void FileSystemWatcher_EventHandler( object sender, FileSystemEventArgs e) { Invoke( new Action( new Action(() => { Console.WriteLine(e.Name+e.FullPath); }))); } //重命名事件的处理方法 private void FileSystemWatcher_Renamed( object sender, RenamedEventArgs e) { Invoke( new Action( new Action(() => { Console.WriteLine(e.OldName+e.Name+e.FullPath); }))); } //错误事件的处理方法 private void FileSystemWatcher_Error( object sender, ErrorEventArgs e) { Invoke( new Action( new Action(() => { Console.WriteLine(e.ToString())); }))); } |
这里需要注意一个问题:因为FileSystemWatcher类本身就是一个多线程的控件,在实例化一个FileSystemWatcher时就自动创建了一个线程,在事件处理的方法中需要使用委托的方式封送到主线程中处理。
1
2 | //声明传递文件Created、Changed、Deleted对象和委托,用于文件增加、删除、修改时更新UI界面 private delegate void setLogDelegate(FileSystemEventArgs e); |
三、展示监控记录
监控的记录可以保存到文件和数据库中,这里就增加一个listView来展示就好了
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 | using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace FileWatcher { public partial class Form1 : Form { private delegate void renameDelegate(RenamedEventArgs e); //声明传递RenamedEventArgs对象和委托,用于文件Renamed时更新UI界面 private delegate void setLogDelegate(FileSystemEventArgs e); //声明传递文件Created、Changed、Deleted对象和委托,用于文件增加、删除、修改时更新UI界面 private FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); private ColumnHeader chTime = new ColumnHeader(); private ColumnHeader chEvent = new ColumnHeader(); private ColumnHeader chFile = new ColumnHeader(); private ColumnHeader chPath = new ColumnHeader(); public Form1() { InitializeComponent(); chTime.TextAlign = HorizontalAlignment.Center; chTime.Width = 130; chTime.Text = "时间" ; this .listViewInfo.Columns.Add(chTime); chEvent.TextAlign = HorizontalAlignment.Center; chEvent.Width = 80; chEvent.Text = "事件" ; this .listViewInfo.Columns.Add(chEvent); chFile.Width = 270; chFile.Text = "文件" ; this .listViewInfo.Columns.Add(chFile); chPath.Width = this .listViewInfo.Width - chTime.Width - chEvent.Width - chFile.Width - 21; chPath.Text = "位置" ; this .listViewInfo.Columns.Add(chPath); ColumnHeader chEnd = new ColumnHeader(); chEnd.Width = 17; chEnd.Text = "" ; this .listViewInfo.Columns.Add(chEnd); this .listViewInfo.View = View.Details; this .listViewInfo.GridLines = true ; fileSystemWatcher.Changed += new FileSystemEventHandler(FileSystemWatcher_EventHandler); fileSystemWatcher.Created += new FileSystemEventHandler(FileSystemWatcher_EventHandler); fileSystemWatcher.Deleted += new FileSystemEventHandler(FileSystemWatcher_EventHandler); fileSystemWatcher.Renamed += new RenamedEventHandler(FileSystemWatcher_Renamed); fileSystemWatcher.Error += new ErrorEventHandler(FileSystemWatcher_Error); fileSystemWatcher.IncludeSubdirectories = true ; fileSystemWatcher.EnableRaisingEvents = true ; } #region 文件增加、删除、修改时被调用的处理方法 private void FileSystemWatcher_EventHandler( object sender, FileSystemEventArgs e) { if (listViewInfo.InvokeRequired) //判断是否跨线程 { listViewInfo.Invoke( new setLogDelegate(SetLog), new object [] { e }); //使用委托将方法封送到UI主线程处理 } } private void SetLog(FileSystemEventArgs e) { string strLog = "" ; switch (e.ChangeType.ToString()) { case "Created" : strLog = "文件创建" ; break ; case "Changed" : strLog = "文件修改" ; break ; case "Deleted" : strLog = "文件删除" ; break ; default : strLog = e.ChangeType.ToString(); break ; } ListViewItem lvi = new ListViewItem(); lvi.Text = DateTime.Now.ToString( "yyyy-MM-dd HH:mm:ss" ); lvi.SubItems.Add(strLog); lvi.SubItems.Add(e.Name); lvi.SubItems.Add(e.FullPath.Replace(e.Name, "" )); listViewInfo.Items.Add(lvi); } #endregion #region 重命名方法 private void FileSystemWatcher_Renamed( object sender, RenamedEventArgs e) { if (listViewInfo.InvokeRequired) { listViewInfo.Invoke( new renameDelegate(SetRenamedLog), new object []{e}); } } private void SetRenamedLog(RenamedEventArgs e) { //listViewInfo.Items.Add(string.Format("重命名:{0} 被换名为:{1}, {2}", e.OldName, e.Name, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))); ListViewItem lvi = new ListViewItem(); lvi.Text = DateTime.Now.ToString( "yyyy-MM-dd HH:mm:ss" ); lvi.SubItems.Add( "文件重命名" ); lvi.SubItems.Add(e.OldName + "被换名为:" + e.Name); lvi.SubItems.Add(e.FullPath.Replace(e.Name, "" )); listViewInfo.Items.Add(lvi); } #endregion #region 错误事件的方法 private void FileSystemWatcher_Error( object sender, ErrorEventArgs e) { if (listViewInfo.InvokeRequired) //判断是否跨线程 { //使用委托处理 Invoke( new Action( new Action(() => { listViewInfo.Items.Add( string .Format( "文件出错:{0}, {1}" , e.ToString(), DateTime.Now.ToString( "yyyy-MM-dd HH:mm:ss" ))); }))); } } #endregion } } |
以上就是C#利用FileSystemWatcher实时监控文件的增加,修改,重命名和删除的详细内容。