C# FileSystemWatcher实现单个文件监控

现在有这样一个简单的需求(做成windows系统服务):监控一个aspx文件,如果有变化,包括修改、删除、重命名等,就用原来的文件替换被修改过的文件,并向管理员发送一封通知邮件。

C#中包含有一个FileSystemWatcher对象,它可以为你完成目录监控工作。如果新建、更新、重命名或删除一个文件,FileSystemWatcher将提交一个事件,通知你发生了一项改变。这样,新建一个文件后,你的程序立即就知道可以使用这个文件。立即通知改变使得你的系统以更高的效率工作,因为你不能总是“调查”目录中发生的改变,而且在两次目录扫描之间也不会有时间流失。

FileSystemWatcher的基础信息请参考FileSystemWatcher 类(System.IO),在此不再赘述。

本文将主要解决当一个事件发生时,引起的change事件触发多次的问题。

namespace FileMonitorService
{
    public partial class Service1 : ServiceBase
    {
        
        FileSystemWatcher watcher = new FileSystemWatcher();//监控类实例

        static void Main(string[] args) {
            System.ServiceProcess.ServiceBase.Run(new Service1());//主函数调用,启动服务
        }

        public Service1()
        {
            InitializeComponent();
            this.ServiceName = "FileMonitorService";//初始化服务名
            this.CanPauseAndContinue = true;//服务可以暂停和继续
            this.CanStop = true;//服务可以被停止
        }
        protected override void OnStart(string[] args)//重载start方法
        {
            try
            {
//设置监控类的基础信息
                watcher.BeginInit();
                watcher.IncludeSubdirectories = true;
                watcher.Path = @"C:\测试";
                watcher.Filter = "test.aspx";
                watcher.Changed += new FileSystemEventHandler(OnChanged);
                watcher.Renamed += new RenamedEventHandler(OnRenamed);
                watcher.EndInit();
                watcher.EnableRaisingEvents = true;
            }
            catch (System.IO.IOException ext) {
                Console.WriteLine(ext.Message);
            }
        }


        private void OnChanged(object source,FileSystemEventArgs e) {
            string path = "F" + e.FullPath.Substring(1, e.FullPath.Length - 1);
            string message = "";
            if (System.IO.File.Exists(path))
            {
                try
                {
                    watcher.EnableRaisingEvents = false; //监控到改变事件,文件被修改了,现在要改回去,在改回去前停止进行文件的监控,解决触发多次的问题
                    File.Copy(path, e.FullPath, true);
                    message = "成功复制文件" + path + "到" + e.FullPath;

                }
                catch (System.IO.IOException ext)
                {
                    Console.WriteLine(ext.Message);
                }
                finally
                {
                    watcher.EnableRaisingEvents = true;//文件被还原后,再次启动监控
                }
            }
            else
            {
                message = "在原盘中不存在被修改的文件夹或文件,请查看服务器确认,手动还原!";
            }
            SendMail mail = new SendMail();
            mail.Send();
           
        }
        private void OnRenamed(object source, RenamedEventArgs e)
        {
            
            Console.WriteLine("文件重命名事件处理逻辑:" + e.OldFullPath + " 被重命名为 " + e.FullPath);
            string path = "F" + e.OldFullPath.Substring(1, e.OldFullPath.Length - 1);
            string message = "";
            if (System.IO.File.Exists(path))
            {

                try
                {
                    watcher.EnableRaisingEvents = false;
                    File.Move(e.FullPath, e.OldFullPath);//复制文件
                    message = "成功还原文件" + e.FullPath;

                }
                catch (System.IO.IOException ext)
                {
                    Console.WriteLine(ext.Message);
                }
                finally
                {
                    watcher.EnableRaisingEvents = true;
                }
            }
            else if (System.IO.Directory.Exists(path))
            {
                try
                {
                    watcher.EnableRaisingEvents = false;
                    Directory.Move(e.FullPath, e.OldFullPath);//复制文件夹
                    message = "成功还原文件夹" + e.FullPath;


                }
                catch (System.IO.IOException ext)
                {
                    Console.WriteLine(ext.Message);
                }
                finally
                {
                    watcher.EnableRaisingEvents = true;
                }
            }
            else
            {

                message = "在原盘中不存在被修改的文件夹或文件,请查看服务器确认,手动还原!";
            }
            SendMail mail = new SendMail();
            mail.Send();
        }

        public static void CopyDirectory(string sourceDirName, string destDirName)
        {
            //采用递归的方法实现对文件夹的复制
        }

        protected override void OnStop()//重载stop方法,停止监控
        {
            watcher.EnableRaisingEvents = false;
        }

        protected override void OnPause()//重载pause方法,停止监控
        {
            watcher.EnableRaisingEvents = false;
        }

        protected override void OnContinue()//重载continue方法,启动监控
        {
            watcher .EnableRaisingEvents = true ;
        }
    }

    public class SendMail//发送邮件类
    {
        public SendMail(string from, string to, string title, string body, string password){}

		public void Send(){}
        .......................
    }
}

对于单个文件,以上的方法可以解决触发多次change事件的问题,但对于一个文件系统来说,这个方法是不可行的,因为对于整个文件系统来说,它包含很多文件,当其中的一个文件被修改时,这时停止了对系统监控,同时又有其它文件被修改,这就无法被监控到,文件的事件很可能丢失。针对文件系统的监控,本人也在实现中,如果有什么好的方法,希望大家分享。

文章目录
|