当前位置: 首页 > 知识库问答 >
问题:

为什么你要跟踪目录。删除目录不是空的

曾永新
2023-03-14

我正在创建一个目录,并在上面设置一个文件系统监视程序。然后我创建一个文件。所有这些都是在表单构造函数中完成的。在按钮事件处理程序中,我删除了上面创建的目录。有时它会抛出一个IOException:目录不是空的。在此之后,我甚至无法访问资源管理器中的子目录。我一直拒绝访问错误。我的进程退出后,此目录将被删除。AFAIK FileSystemWatcher不应锁定目录。


        string alphaBeta = @"Alpha\Beta";
        public Form1()
        {
            InitializeComponent();
            Directory.CreateDirectory(alphaBeta);
            FileSystemWatcher watcher = new FileSystemWatcher()
            {
                Path = alphaBeta,
                Filter = "*.dat",
                NotifyFilter = NotifyFilters.FileName
            };
            watcher.EnableRaisingEvents = true;
            File.WriteAllText(alphaBeta + @"\Gamma.dat", "Delta");
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            Directory.Delete("Alpha", true);//Recursively Delete
        }

如何正确删除目录而不会卡住目录?

更新:以上是最小可重复的例子

我的实际场景涉及在explorer中加载的加载项。监视配置目录的更改的exe。它与FSW的创建和重命名事件挂钩。

删除代码在卸载程序中运行。卸载程序不应该杀死explorer。我们认为FileSystemWatcher不会锁定文件夹,并且在删除目录后会自动停止监视更改。但事实似乎并非如此。

共有2个答案

荀增
2023-03-14

这似乎是FileSystemWatcher的问题。如果注释掉此代码,则不会发生异常。

似乎FileSystemWatcher不一定是在目录之前处理的。调用Delete方法。

处理FileSystemWatcher的方式可以使其在删除可能依赖的资源之前得到处理,但在您的示例代码中,只需添加watcher即可轻松实现。Dispose()

string alphaBeta = @"Alpha\Beta";
public Form1()
{
    InitializeComponent();
    Directory.CreateDirectory(alphaBeta);
    FileSystemWatcher watcher = new FileSystemWatcher()
    {
        Path = alphaBeta,
        Filter = "*.dat",
        NotifyFilter = NotifyFilters.FileName
    };
    watcher.EnableRaisingEvents = true;
    watcher.Dispose();
    File.WriteAllText(alphaBeta + @"\Gamma.dat", "Delta");
}

private void button1_Click(object sender, EventArgs e)
{

    Directory.Delete("Alpha", true);//Recursively Delete
}

卢开济
2023-03-14

导致该问题的原因是,只要启用了事件,FSW就会保持目录的句柄处于打开状态。源代码显示,禁用事件也会关闭句柄。要删除目录,必须禁用FSW。

第二个问题是,FileSystemWatcher-watcher被定义为Form1()构造函数中的一个变量,这意味着它是孤立的,在表单显示之前就可以立即进行垃圾收集。不过,垃圾收集器很少运行,这意味着不能保证它会在单击Delete之前运行。由于watcher没有存储在任何地方,因此无法再禁用它。

至少,FSW需要存储在字段中,并且在删除之前禁用事件。我们还应该确保当表单本身被处理时,观察者被处理:

public class Form1
{
    FileSystemWatcher _watcher;

    public Form1()
    {
        ...
        _watcher=CreateDormantWatcher(path,pattern);
        _watcher.EnableRaisingEvents=true ;
    }

    private void btnDelete_Click(object sender, EventArgs e)
    {
        _watcher.EnableRaisingEvents =false;
        Directory.Delete("Alpha", true);//Recursively Delete
    }

    protected override void Dispose (bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
        {
             _watcher.Dispose();
        }
        _watcher=watcher;
    }

    FileSystemWatcher CreateDormantWatcher(string path,string pattern)
    {
        //Don't store to the field until the FSW is 
        //already configured
        var watcher=new FileSystemWatcher()
        {
            Path = path,
            Filter = "pattern,
            NotifyFilter = NotifyFilters.FileName
        };
        watcher.Changed += OnChanged;
        watcher.Created += OnCreated;
        watcher.Deleted += OnChanged;
        watcher.Renamed += OnRenamed;
        return watcher;
    }

简单修复:将其添加为组件

也许一个更好的主意是在表单上添加FileSystemWatcher作为组件。FileSystemWatcher继承自Component,这意味着将其放在窗体上,在初始组件()中添加其创建和配置代码。当所有其他组件被处理时,它也会被处理掉。

如果我们这样做,我们只需要在适当的时候切换EnableRaisingEvents

假设路径和模式被设置为属性,并且组件的名称是富有想象力的FileSystemWatcher1,这将代码归结为:

    public Form1()
    {
        InitializeComponent();
        Directory.CreateDirectory(FileSystemWatcher1.Path);
        FileSystemWatcher1.EnableRaisingEvents = true;
        File.WriteAllText(alphaBeta + @"\Gamma.dat", "Delta");
    }

    private void btnDelete_Click(object sender, EventArgs e)
    {
        FileSystemWatcher1.EnableRaisingEvents = false;
        Directory.Delete("Alpha", true);//Recursively Delete
    }
 类似资料:
  • 问题内容: 在我的Node应用程序中,我需要删除一个包含一些文件的目录,但仅适用于空目录。我怎样才能做到这一点? 问题答案: 为此有一个名为(https://npmjs.org/package/rimraf)的模块。它提供的功能与 异步 用法: 同步 使用情况:

  • 嗨,当我想删除空目录时,我遇到以下错误: 警告:rmdir():目录不为空 功能: 当有文件时,它会在没有警告的情况下删除所有文件(也应该删除文件夹)

  • 我是詹金斯的新用户。我最近遇到了一个失败的产品构建,在该构建中,我看到该特定产品的过去未跟踪的Maven模块被添加到当前要构建的现有Maven模块集中。

  • 和 mkdir 命令(创建空目录)恰好相反,rmdir(remove empty directories 的缩写)命令用于删除空目录,此命令的基本格式为: [root@localhost ~]# rmdir [-p] 目录名 -p 选项用于递归删除空目录。 【例 1】 [root@localhost ~]#rmdir cangls 就这么简单,命令后面加目录名称即可,但命令执行成功与否,取决于要删

  • 每当我试图使用它们来删除包含内容的dir时,我都会收到此错误消息 “/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py”,removedirs rmdir(name)OSError:[Errno 66]目录中的第170行非空:“新文件” 然而,我认为我看到人们使用这些命令来删除不是空的目录,那么我做错了什么?谢

  • 我在为JDK选择主目录时遇到了一个问题。即使我选择了以下路径:“C:\Program Files(x86)\java\jre1.8.0_91”,它仍然显示错误:“所选目录不是JDK的有效主目录”。我的java文件夹有两个文件夹-bin和lib。选择主目录的窗口 请帮助我选择主目录。谢谢!