Previous topicNext topic
Help > 开发指南 > 窗体开发 > 控件参考 > 控件参考 > 其他 >
FileSystemWatcher(文件监测)

FileSystemWatcher用于监视指定目录中的更改。 可以监视指定目录的文件和子目录中的更改。 可以创建组件来监视本地计算机、网络驱动器或远程计算机上的文件。

若要监视所有文件中的更改,请将 Filter 属性设置为空字符串 (“”) 或使用通配符 (“*.*”) 。 若要监视特定文件,请将 Filter 属性设置为文件名。 例如,若要监视文件MyDoc.txt中的更改,请将 Filter 属性设置为“MyDoc.txt”。 还可以监视特定类型的文件中的更改。 例如,若要监视文本文件中的更改,请将 Filter 属性设置为“*.txt”。

可以在目录或文件中监视多种类型的更改。 例如,可以监视文件或目录的更改、Attributes、LastWrite日期和时间或目录和文件的Size。 通过将属性设置为 NotifyFilter 其中一个 NotifyFilters 值来完成此操作。 有关可监视的更改类型的详细信息,请参阅 NotifyFilters。

NotifyFilters枚举列表如下:

Attributes 4

文件或文件夹的属性。

CreationTime 64

文件或文件夹的创建时间。

DirectoryName 2

目录名。

FileName 1

文件的名称。

LastAccess 32

文件或文件夹上一次打开的日期。

LastWrite 16

上一次向文件或文件夹写入内容的日期。

Security 256

文件或文件夹的安全设置。

Size 8

文件或文件夹的大小。

可以监视重命名、删除或创建文件或目录。 例如,若要监视文本文件的重命名,请将Filter属性设置为“*.txt”,并使用为其参数指定的方法Renamed进行调用WaitForChanged。

Windows操作系统将FileSystemWatcher创建的缓冲区中的文件更改通知给FileSystemWatcher组件。 如果短时间内发生了许多更改,则缓冲区可能会溢出。 这会导致组件丢失对目录中的更改的跟踪,并且只会提供全面通知。 使用 InternalBufferSize 属性增加缓冲区的大小是昂贵的,因为它来自无法交换到磁盘的非分页内存,因此使缓冲区保持较小但足够大,无法错过任何文件更改事件。 若要避免缓冲区溢出,请使用 NotifyFilter 和 IncludeSubdirectories 属性,以便筛选掉不需要的更改通知。

使用 FileSystemWatcher 类时,请注意以下事项。

1、不忽略隐藏的文件。

2、在某些系统中, FileSystemWatcher 报告使用短 8.3 文件名格式对文件的更改。 例如,对“LongFileName.LongExtension”的更改可以报告为“LongFil~.Lon”。

3、此类包含应用于所有成员的类级别的链接需求和继承需求。 当直接调用方或派生类没有完全信任权限时,将引发一个SecurityException异常。

可以为通过网络监视目录的属性设置 InternalBufferSize 的最大大小为 64 KB。

复制和移动文件夹
操作系统和 FileSystemWatcher 对象将剪切和粘贴操作或移动操作解释为文件夹及其内容的重命名操作。 如果将包含文件的文件夹剪切并粘贴到要监视的文件夹中,则 FileSystemWatcher 对象仅将文件夹报告为新文件夹,但不报告其内容,因为它们实质上只是重命名。

若要通知文件夹的内容已移动或复制到监视文件夹中, OnChanged 请提供和 OnRenamed 事件处理程序方法,如下表所示。

事件处理程序 处理的事件 执行速度
OnChanged Changed, Created, Deleted 报告文件属性、创建的文件和已删除文件中的更改。
OnRenamed Renamed 列出重命名的文件和文件夹的旧路径和新路径,根据需要以递归方式扩展。

事件和缓冲区大小
请注意,多种因素可能会影响引发哪些文件系统更改事件,如下所述:

1、常见的文件系统操作可能会引发多个事件。 例如,将文件从一个目录移动到另一个目录时,可能会引发多个OnChanged文件和OnCreatedOnDeleted事件。 移动文件是包含多个简单操作的复杂操作,因此引发多个事件。 同样,某些应用程序 (例如,防病毒软件) 可能会导致检测到 FileSystemWatcher其他文件系统事件。

2、只要磁盘未切换或删除,就可以 FileSystemWatcher 监视磁盘。 不会 FileSystemWatcher 引发 CD 和 DVD 的事件,因为时间戳和属性无法更改。 远程计算机必须安装一个必需的平台,组件才能正常运行。

请注意,超过缓冲区大小时,可能会 FileSystemWatcher 错过事件。 若要避免缺少事件,请遵循以下准则:

1、通过设置 InternalBufferSize 属性来增加缓冲区大小。

2、避免监视具有长文件名的文件,因为长文件名有助于填充缓冲区。 请考虑使用较短的名称重命名这些文件。

3、尽量缩短事件处理代码。

属性

属性名称 描述
EnableRaisingEvents 获取或设置一个值,该值指示是否启用此组件。
Filter 获取或设置用于确定在目录中监视哪些文件的筛选器字符串。
Filters 获取用于确定在目录中监视哪些文件的所有筛选器的集合。
IncludeSubdirectories 获取或设置一个值,该值指示是否应监视指定路径中的子目录。
InternalBufferSize 获取或设置内部缓冲区的大小(以字节为单位)。
NotifyFilter 获取或设置要监视的更改的类型。
Path 获取或设置要监视的目录的路径。
SynchronizingObject 获取或设置用于封送因目录更改而发出的事件处理程序调用的对象。

方法

方法名称 说明
WaitForChanged(WatcherChangeTypes) 一种同步方法,在给定要监视的更改的类型情况下,它会返回包含已发生的更改上的特定信息的结构。
WaitForChanged(WatcherChangeTypes, Int32) 一种同步方法,在给定要监视的更改的类型以及在超时前等待的时间(以毫秒表示)的情况下,它会返回包含已发生的更改上的特定信息的结构。

事件

事件名称 说明
Changed 当更改指定 Path 中的文件和目录时发生。
Created 当在指定 Path 中创建文件和目录时发生。
Deleted 删除指定 Path 中的文件或目录时发生。
Error 当 FileSystemWatcher 的实例无法继续监视更改或内部缓冲区溢出时发生。
Renamed 重命名指定 Path 中的文件或目录时发生。

下面我们就以一个示例来说明一下该组件该如何使用。

第一步,按照下面的布局创建窗体。

第二步,设置drpPath控件的属性如下,方便直接弹出窗口选择目录。

第三步,在窗体Load事件,命令按钮的单击事件,以及在FileSystemWatcher所有的事件中添加代码,用来在界面中反应监测结果。

Vb.Net
Imports System
Imports System.Text
Imports System.IO
Imports System.Data
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.Drawing.Text
Imports System.Diagnostics
Imports System.Collections
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports System.Collections.Specialized
Imports System.Windows.Forms
Imports System.Reflection
Imports Microsoft.CSharp
Imports Microsoft.VisualBasic
Imports sanMuSoft.Utility
Imports sanMuSoft.Data.Pivot
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Xml
Imports System.Data.Common
Imports System.Net.Http
Imports C1.C1Excel
Imports C1.C1Zip
Imports C1.Win.C1Command
Imports C1.Win.C1FlexGrid
Imports C1.Win.C1Input
Imports C1.Win.C1Ribbon
Imports C1.Win.C1Themes
Imports sanMuSoft.CS.Framework
Imports sanMuSoft.CS.Framework.Editor
Imports sanMuSoft.CS.Framework.FormDesigner
Imports sanMuSoft.CS.Framework.DropDownForms
Imports sanMuSoft.CS.WinForm
Imports sanMuSoft.CS.WinForm.Editor
Imports sanMuSoft.CS.WinForm.Controls
Imports sanMuSoft.CS.WinForm.Controls.Grid
Imports sanMuSoft.CS.WinForm.Controls.BoxControls
Imports sanMuSoft.CS.Workflow
Imports sanMuSoft.CS.Report
Imports sanMuSoft.Data
Imports sanMuSoft.Data.TableBuilder
Imports sanMuSoft.CS.ShareFunc
Imports Newtonsoft.Json.Linq
Imports Newtonsoft.Json
Imports Aliyun.OSS

Namespace FormEvents
    Public Class Form0c942ea21feb488d88abcd3b5d48deed
        Inherits FormEventsBase
        Private FileSystemWatcher1 As FileSystemWatcher
        Private btnStart As SmButton
        Private btnStop As SmButton
        Private chkEnableRaisingEvents As SmCheckBox
        Private chkIncludeSubdirectories As SmCheckBox
        Private cmbNotifyFilter As SmCheckedComboBox
        Private drpPath As SmFilePathSelectBox
        Private lblStatus As SmLabel
        Private lstMsg As SmListBox
        Private txtFilter As SmTextBox
        Public Sub FileSystemWatcherHelp_Load(sender As Object,e As  System.EventArgs)
            '初始化相应的私有变量,方便在其他事件中直接引用
            FileSystemWatcher1=Me.SmForm.Components.Components("FileSystemWatcher1")
            btnStart=Me.SmForm.ControlDictionary()("btnStart")
            btnStop=Me.SmForm.ControlDictionary()("btnStop")
            chkEnableRaisingEvents=Me.SmForm.ControlDictionary()("chkEnableRaisingEvents")
            chkIncludeSubdirectories=Me.SmForm.ControlDictionary()("chkIncludeSubdirectories")
            cmbNotifyFilter=Me.SmForm.ControlDictionary()("cmbNotifyFilter")
            drpPath=Me.SmForm.ControlDictionary()("drpPath")
            lblStatus=Me.SmForm.ControlDictionary()("lblStatus")
            lstMsg=Me.SmForm.ControlDictionary()("lstMsg")
            txtFilter=Me.SmForm.ControlDictionary()("txtFilter")
            
            '加载NotifyFilters类型的清单
            cmbNotifyFilter.ItemsBindingDictionary=EnumExtensions.GetEnumDictionaryKeyFirst(Of NotifyFilters)()
            cmbNotifyFilter.Text=FileSystemWatcher1.NotifyFilter.ToString()
            txtFilter.Text="*.*"
            
        End Sub
        
        Public Sub btnStart_Click(sender As Object,e As  System.EventArgs)
            If String.IsNullOrEmpty(drpPath.Text) Then
                MessageBox.Show("请先设置好监测目录后再执行此操作!")
                Return
            End If
            '设置监视目录
            FileSystemWatcher1.Path=drpPath.Text
            '是否包含子目录
            FileSystemWatcher1.IncludeSubdirectories=chkIncludeSubdirectories.Checked
            '设置监视筛选条件,
            FileSystemWatcher1.Filter=txtFilter.Text
            '设置监听类型
            FileSystemWatcher1.NotifyFilter=cmbNotifyFilter.Text.CType(Of NotifyFilters)
            '打开文件监视控件的监视状态
            FileSystemWatcher1.EnableRaisingEvents=True
            '属性状态
            chkEnableRaisingEvents.Checked=True
            '显示状态
            lblStatus.BackColor=Color.Green
        End Sub
        
        Public Sub btnStop_Click(sender As Object,e As  System.EventArgs)
            '关闭文件监视控件的监视状态
            FileSystemWatcher1.EnableRaisingEvents=False
            '属性状态
            chkEnableRaisingEvents.Checked=False
            '显示状态
            lblStatus.BackColor=Color.Red
        End Sub
        
        Public Sub FileSystemWatcher1_Changed(sender As Object,e As  System.IO.FileSystemEventArgs)
            lstMsg.Items.Add("事件:Changed,文件目录:" & e.FullPath)
        End Sub
        
        Public Sub FileSystemWatcher1_Created(sender As Object,e As  System.IO.FileSystemEventArgs)
            lstMsg.Items.Add("事件:Created,文件目录:" & e.FullPath)
        End Sub
        
        Public Sub FileSystemWatcher1_Deleted(sender As Object,e As  System.IO.FileSystemEventArgs)
            lstMsg.Items.Add("事件:Deleted,文件目录:" & e.FullPath)
        End Sub
        
        Public Sub FileSystemWatcher1_Renamed(sender As Object,e As  System.IO.RenamedEventArgs)
            lstMsg.Items.Add("事件:Renamed,原目录:" & e.OldFullPath & ",新目录:" & e.FullPath)
        End Sub
        
        Public Sub lstMsg_MouseDoubleClick(sender As Object,e As  System.Windows.Forms.MouseEventArgs)
            '双击将文本复制到剪贴板
            If lstMsg.SelectedItem IsNot Nothing Then
                Clipboard.SetText(lstMsg.SelectedItem.ToString())
            End If
        End Sub
        
    End Class
End Namespace

C#
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Collections;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.Windows.Forms;
using Microsoft.CSharp;
using sanMuSoft.Utility;
using sanMuSoft.Data.Pivot;
using System.Threading;
using System.Xml;
using System.Data.Common;
using System.Net.Http;
using C1.C1Excel;
using C1.C1Zip;
using C1.Win.C1Command;
using C1.Win.C1FlexGrid;
using C1.Win.C1Input;
using C1.Win.C1Ribbon;
using C1.Win.C1Themes;
using sanMuSoft.CS.Framework;
using sanMuSoft.CS.Framework.Editor;
using sanMuSoft.CS.Framework.FormDesigner;
using sanMuSoft.CS.Framework.DropDownForms;
using sanMuSoft.CS.WinForm;
using sanMuSoft.CS.WinForm.Editor;
using sanMuSoft.CS.WinForm.Controls;
using sanMuSoft.CS.WinForm.Controls.Grid;
using sanMuSoft.CS.WinForm.Controls.BoxControls;
using sanMuSoft.CS.Workflow;
using sanMuSoft.CS.Report;
using sanMuSoft.Data;
using sanMuSoft.Data.TableBuilder;
using sanMuSoft.CS.ShareFunc;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Aliyun.OSS;

namespace FormEvents
{
    public class Form0c942ea21feb488d88abcd3b5d48deed : FormEventsBase
    {
        private FileSystemWatcher FileSystemWatcher1;
        private SmButton btnStart;
        private SmButton btnStop;
        private SmCheckBox chkEnableRaisingEvents;
        private SmCheckBox chkIncludeSubdirectories;
        private SmCheckedComboBox cmbNotifyFilter;
        private SmFilePathSelectBox drpPath;
        private SmLabel lblStatus;
        private SmListBox lstMsg;
        private SmTextBox txtFilter;
        public void FileSystemWatcherHelp_Load(object sender, System.EventArgs e)
        {
            // 初始化相应的私有变量,方便在其他事件中直接引用
            FileSystemWatcher1 = this.SmForm.Components.Components["FileSystemWatcher1"] as FileSystemWatcher;
            btnStart = this.SmForm.ControlDictionary()["btnStart"] as SmButton;
            btnStop = this.SmForm.ControlDictionary()["btnStop"] as SmButton;
            chkEnableRaisingEvents = this.SmForm.ControlDictionary()["chkEnableRaisingEvents"] as SmCheckBox;
            chkIncludeSubdirectories = this.SmForm.ControlDictionary()["chkIncludeSubdirectories"] as SmCheckBox;
            cmbNotifyFilter = this.SmForm.ControlDictionary()["cmbNotifyFilter"] as SmCheckedComboBox;
            drpPath = this.SmForm.ControlDictionary()["drpPath"] as SmFilePathSelectBox;
            lblStatus = this.SmForm.ControlDictionary()["lblStatus"] as SmLabel;
            lstMsg = this.SmForm.ControlDictionary()["lstMsg"] as SmListBox;
            txtFilter = this.SmForm.ControlDictionary()["txtFilter"] as SmTextBox;

            // 加载NotifyFilters类型的清单
            cmbNotifyFilter.ItemsBindingDictionary = EnumExtensions.GetEnumDictionaryKeyFirst<NotifyFilters>();
            cmbNotifyFilter.Text = FileSystemWatcher1.NotifyFilter.ToString();
            txtFilter.Text = "*.*";
        }

        public void btnStart_Click(object sender, System.EventArgs e)
        {
            if (string.IsNullOrEmpty(drpPath.Text))
            {
                MessageBox.Show("请先设置好监测目录后再执行此操作!");
                return;
            }
            // 设置监视目录
            FileSystemWatcher1.Path = drpPath.Text;
            // 是否包含子目录
            FileSystemWatcher1.IncludeSubdirectories = chkIncludeSubdirectories.Checked;
            // 设置监视筛选条件,
            FileSystemWatcher1.Filter = txtFilter.Text;
            // 设置监听类型
            FileSystemWatcher1.NotifyFilter = cmbNotifyFilter.Text.CType<NotifyFilters>;
            // 打开文件监视控件的监视状态
            FileSystemWatcher1.EnableRaisingEvents = true;
            // 属性状态
            chkEnableRaisingEvents.Checked = true;
            // 显示状态
            lblStatus.BackColor = Color.Green;
        }

        public void btnStop_Click(object sender, System.EventArgs e)
        {
            // 关闭文件监视控件的监视状态
            FileSystemWatcher1.EnableRaisingEvents = false;
            // 属性状态
            chkEnableRaisingEvents.Checked = false;
            // 显示状态
            lblStatus.BackColor = Color.Red;
        }

        public void FileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            lstMsg.Items.Add("事件:Changed,文件目录:" + e.FullPath);
        }

        public void FileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            lstMsg.Items.Add("事件:Created,文件目录:" + e.FullPath);
        }

        public void FileSystemWatcher1_Deleted(object sender, System.IO.FileSystemEventArgs e)
        {
            lstMsg.Items.Add("事件:Deleted,文件目录:" + e.FullPath);
        }

        public void FileSystemWatcher1_Renamed(object sender, System.IO.RenamedEventArgs e)
        {
            lstMsg.Items.Add("事件:Renamed,原目录:" + e.OldFullPath + ",新目录:" + e.FullPath);
        }

        public void lstMsg_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            // 双击将文本复制到剪贴板
            if (lstMsg.SelectedItem != null)
                Clipboard.SetText(lstMsg.SelectedItem.ToString());
        }
    }
}

最后执行窗体运行效果如下: