1

我有一个程序可以监视特定文件的创建和删除以执行特定操作。我们使用 .NET FileSystemWatcher 来监视围绕这些特定文件的活动。该程序在 .NET 3.5 上作为 Windows 服务运行,并使用 C# 编码。我们遇到了一个问题,即使用 Windows DEL 命令或 ERASE 命令删除正在监视的文件不会触发任何 FileSystemWatcher 事件(更改、删除、创建、错误、重命名)。这似乎只是我的 Windows 2003 和 Windows 2008 机器上的问题,而不是我的 Windows 7 机器上的问题。它在 Windows 7 上运行良好。为此我在 Google 上进行了广泛搜索,并查看了几篇 StackOverflow 帖子,但都没有运气。我玩过 FileSystemWatcher 的不同配置 - 增加了缓冲区,尝试了 NotifyFilter 枚举的各种组合,打开 IncludeSubdirectories,增加和减少涉及修改文件和运行程序的用户的权限 - 所有这些都没有成功。我在我的事件处理程序的顶部放置了一个断点,它永远不会碰到 DEL 或 ERASE。它确实适用于创建和重命名 (REN)。作为一种解决方法,我们只是在删除文件之前重命名文件。但我想知道是否有解决方案。我可以通过某种方式对其进行编码,或者是否可以在 Windows 框上更改某些配置,这将导致服务获取 DEL 或 ERASE。这是我的文件观察器的代码(为简洁起见,删除了评论):我在我的事件处理程序的顶部放置了一个断点,它永远不会碰到 DEL 或 ERASE。它确实适用于创建和重命名 (REN)。作为一种解决方法,我们只是在删除文件之前重命名文件。但我想知道是否有解决方案。我可以通过某种方式对其进行编码,或者是否可以在 Windows 框上更改某些配置,这将导致服务获取 DEL 或 ERASE。这是我的文件观察器的代码(为简洁起见,删除了评论):我在我的事件处理程序的顶部放置了一个断点,它永远不会碰到 DEL 或 ERASE。它确实适用于创建和重命名 (REN)。作为一种解决方法,我们只是在删除文件之前重命名文件。但我想知道是否有解决方案。我可以通过某种方式对其进行编码,或者是否可以在 Windows 框上更改某些配置,这将导致服务获取 DEL 或 ERASE。这是我的文件观察器的代码(为简洁起见,删除了评论):或者是否有一些我可以在 Windows 框中更改的配置会导致服务获取 DEL 或 ERASE。这是我的文件观察器的代码(为简洁起见,删除了评论):或者是否有一些我可以在 Windows 框中更改的配置会导致服务获取 DEL 或 ERASE。这是我的文件观察器的代码(为简洁起见,删除了评论):

using System;
using System.IO;
using System.Runtime.Serialization;

namespace GatewayEDI.ClaimRouter.FileManagement
{
    public delegate void FileChangedEventHandler(object sender, FileChangedEventArgs e);

    public enum Status
    {
        Added,
        Changed,
        Deleted,
        Unknown
    }

    public class FolderWatcher : IDisposable
    {
        protected FileSystemWatcher Watcher;

        public Status FileStatus
        {
            get;
            set;
        }

        public event FileChangedEventHandler FileChanged;

        public virtual void OnHasFileChanged(FileChangedEventArgs e)
        {
            FileChangedEventHandler fileChanged = FileChanged;
            if (fileChanged != null)
            {
                fileChanged(this, e);
            }
        }

        public FolderWatcher(string path, string file)
        {
            FileStatus = Status.Unknown;
            if (!string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(file))
                CreateFileSystemWatcher(path, file);
        }

        private void CreateFileSystemWatcher(string path, string file)
        {
            Watcher = new FileSystemWatcher();

            try
            {
                if (path.LastIndexOf("\\", StringComparison.CurrentCulture) < path.Length - 1)
                    path += "\\";

                Watcher.Path = path;
                Watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastAccess | NotifyFilters.LastWrite;
                Watcher.Filter = file;

                Watcher.Created += WatcherChanged;
                Watcher.Changed += WatcherChanged;
                Watcher.Renamed += WatcherChanged;
                Watcher.Deleted += WatcherChanged;
                Watcher.Error += WatcherError;
                Watcher.EnableRaisingEvents = true;
            }
            catch (Exception ex)
            {
                FileStatus = Status.Unknown;
                throw new FolderWatcherException("Unexpected exception searching file.  Path = " + Watcher.Path + ".  Error = " + ex.Message, ex);
            }
        }

        void WatcherError(object sender, ErrorEventArgs e)
        {
            FileStatus = Status.Unknown;
            SendFileChangedEvent();
        }

        void WatcherChanged(object sender, FileSystemEventArgs e)
        {
            switch (e.ChangeType)
            {
                case WatcherChangeTypes.Created:
                    FileStatus = Status.Added;
                    break;
                case WatcherChangeTypes.Changed:
                    FileStatus = Status.Changed;
                    break;
                case WatcherChangeTypes.Renamed:
                    FileStatus = e.Name.Equals(Watcher.Filter) ? Status.Added : Status.Deleted;
                    break;
                case WatcherChangeTypes.Deleted:
                    FileStatus = Status.Deleted;
                    break;
                default:
                    FileStatus = Status.Unknown;
                    break;
            }

            SendFileChangedEvent();
        }

        protected void SendFileChangedEvent()
        {
            string fileName = Watcher == null ? string.Empty : Watcher.Filter;
            FileChangedEventArgs args = new FileChangedEventArgs
            {
                FileStatus = FileStatus,
                FileName = fileName
            };
            OnHasFileChanged(args);
        }

        public void DeleteFile()
        {
            FileInfo fi = new FileInfo(Watcher.Path + Watcher.Filter);
            try
            {
                fi.Delete();
            }
            catch (Exception ex)
            {
                throw new FolderWatcherException("Error deleting file.  Path = " + Watcher.Path + ", File = " + Watcher.Filter + ".  Error = " + ex.Message, ex);
            }
        }

        private bool _alreadyDisposed;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool isDisposing)
        {
            if (_alreadyDisposed)
                return;
            if (isDisposing)
            {
                if (Watcher != null)
                    Watcher.Dispose();
            }
            _alreadyDisposed = true;
        }

        ~FolderWatcher()
        {
            Dispose(false);
        }
    }

    [Serializable]
    public class FolderWatcherException : Exception
    {
        public FolderWatcherException()
        {
        }

        public FolderWatcherException(string message) : base(message)
        {
        }

        public FolderWatcherException(string message, Exception inner) : base(message, inner)
        {
        }

        protected FolderWatcherException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
        }
    }
}

我用来修改文件的 Windows 命令是:

Create:  echo creating main flag > Main.flg
Delete:  DEL Main.flg
Rename:  REN Main.flg Main1.flg

我意识到 FileSystemWatcher 可能有些不可靠,但在这种情况下,我可以始终如一地重现该问题。在某个时候,如果时间允许,我们将用更稳定的东西替换这个文件监视组件。

4

1 回答 1

0

我编写了一个小程序,看看是否可以在我自己的 Windows Server 2008 R2 机器上重现此问题。这是我的代码:

using System;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            FileSystemWatcher fsw = new FileSystemWatcher();
            fsw.Path = @"D:\test";
            fsw.Deleted += new FileSystemEventHandler(ReportChange); 
            fsw.Created += new FileSystemEventHandler(ReportChange);
            fsw.EnableRaisingEvents = true;

            Console.In.ReadLine();
        }

        private static void ReportChange(object source, FileSystemEventArgs e)
        {
            // Specify what is done when a file is created or deleted.
            Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
        }
    }
}

我上面的代码成功地报告了我正在监视的目录中的文件删除。

在仔细查看您的代码时,您似乎可以准确地告诉 FSW 要监控的文件。对我来说,这看起来像是一个时间问题。根据您粘贴的代码,我无法判断 FSW 的创建如何适应被删除文件的过程。您确定在删除您要观看的文件之前创建、初始化和启用 FSW?我的怀疑是首先删除该文件,然后创建 FSW 以监视实际上不再存在的特定文件。

于 2012-12-13T21:16:46.850 回答