代码之家  ›  专栏  ›  技术社区  ›  HHK

如何使用FileSystemWatcher监视一个目录并允许它被正确删除?

  •  2
  • HHK  · 技术社区  · 16 年前

    string dir = Environment.CurrentDirectory + @"\a";
    Directory.CreateDirectory(dir);
    FileSystemWatcher watcher = new FileSystemWatcher(dir);
    watcher.IncludeSubdirectories = false;
    watcher.EnableRaisingEvents = true;
    Console.WriteLine("Deleting " + dir);
    Directory.Delete(dir, true);
    if (Directory.Exists(dir))
    {
        Console.WriteLine("Getting dirs of " + dir);
        Directory.GetDirectories(dir);
    }
    Console.ReadLine();
    

    有趣的是,这会引发一个UnauthorizedAccessException Directory.GetDirectories(dir) .

    删除监视的目录将返回无错误的结果,但是Directory.Exists()仍然返回true,并且目录仍然列出。此外,访问目录会导致任何程序的“访问被拒绝”。一旦带有FileSystemWatcher的.NET应用程序退出,目录就会消失。

    如何在允许正确删除目录的同时监视目录?

    4 回复  |  直到 16 年前
        1
  •  5
  •   Hans Passant    16 年前

    文件也存在相同的机制。复习FileShare.Delete

        2
  •  2
  •   MTs    16 年前

     if (new DirectoryInfo(dir).Exists)
    

    而不是:

    if (Directory.Exists(dir))
    
        3
  •  1
  •   VSOP_juDGe    14 年前

        var dir = new DirectoryInfo(path);
        // delete dir in explorer
        System.Diagnostics.Debug.Assert(dir.Exists); // true
        dir.Refresh();
        System.Diagnostics.Debug.Assert(!dir.Exists); // false
    
        4
  •  1
  •   Chris Goldsmith    11 年前

    不幸的是,FileSystemWatcher获取了目录的句柄,这意味着当目录被删除时,仍然有一个被标记为挂起删除的目录的句柄。我尝试了一些实验,似乎可以使用FileSystemWatcher中的错误事件处理程序来识别何时发生这种情况。

        public myClass(String dir)
        {
            mDir = dir;
            Directory.CreateDirectory(mDir);
    
            InitFileSystemWatcher();
    
            Console.WriteLine("Deleting " + mDir);
            Directory.Delete(mDir, true);
        }
        private FileSystemWatcher watcher;
    
        private string mDir;
    
        private void MyErrorHandler(object sender, FileSystemEventArgs args)
        {
            // You can try to recreate the FileSystemWatcher here
            try
            {
                mWatcher.Error -= MyErrorHandler;
                mWatcher.Dispose();
                InitFileSystemWatcher();
            }
            catch (Exception)
            {
                // a bit nasty catching Exception, but you can't do much
                // but the handle should be released now 
            }
            // you might not be able to check immediately as your old FileSystemWatcher
            // is in your current callstack, but it's a start.
        }
    
        private void InitFileSystemWatcher()
        {
            mWatcher = new FileSystemWatcher(mDir);
            mWatcher.IncludeSubdirectories = false;
            mWatcher.EnableRaisingEvents = true;
            mWatcher.Error += MyErrorHandler;
        }