【问题标题】:Strange exception with file access and explorator windows文件访问和资源管理器窗口的奇怪异常
【发布时间】:2012-10-09 10:58:40
【问题描述】:

考虑这个简单的程序:

private static void Main(string[] args)
{
        var directoryName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Directory");

        if (Directory.Exists(directoryName))
            Directory.Delete(directoryName, true);

        Directory.CreateDirectory(directoryName);

        var stream = File.Create(Path.Combine(directoryName, "File")); //throws
        stream.Close();
}

当您简单地执行这个程序时,这可以正常工作。如果您在 Windows 资源管理器中浏览 Directory 然后运行,就会发生奇怪的事情。在这种情况下,我得到 UnautorizedAccessException "Access to the path 'C:\Users\rfurman\AppData\Roaming\Directory\File' is denied."

如果这很奇怪,那么在相同的条件下执行:

private static void Main(string[] args)
{
        var directoryName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Directory");

        if (Directory.Exists(directoryName))
            Directory.Delete(directoryName, true);

        var value = Directory.Exists(directoryName);

        Console.WriteLine(value);
        Console.ReadKey();
 }

如果Directory 在资源管理器中打开,此程序将打印True

我想知道为什么会发生这种情况以及如何防范这种情况。

我使用 Windows 7 和 .net 4。

【问题讨论】:

  • "如果你浏览那个目录"是什么意思?
  • @Luftwaffe:在 Windows 资源管理器中打开该文件夹
  • 所以你的意思是..文件夹在资源管理器中保持打开..对吗?
  • 程序执行时打开。
  • 文件夹真的被删除了吗?

标签: c# windows-explorer


【解决方案1】:

这有点重复: Bizarre directory delete behaviour on SSD drive

资源管理器只是导致文件夹删除的延迟稍长。删除目录不是“完全”同步操作。该目录被标记为删除,但实际删除可能会滞后一点。

AFAIK 这与 NTFS (win2k/Xp) 一样长。

【讨论】:

    【解决方案2】:

    Directory.Delete 内部使用RemoveDirectory win api in Kernel32。 RemoveDirectory 所做的是“标记要删除的目录”。当该目录的最后一个句柄关闭时,该目录被删除。我相信这意味着“在资源管理器离开该文件夹后”

    在我的计算机中不会发生这种情况,因此我无法测试,但我怀疑可能有适合您的方法。基于 NT 的系统有时允许重命名文件和目录,即使它们是打开的。我不知道这是允许的确切情况,但我用它来重命名加载的 dll 文件并编写新的文件,如下所示:

    File.Rename(@"C:\App\test.dll", @"C:\App\test.dll");
    File.Copy(@"C:\App\Update\test.dll-v1.1", @"C:\App\test.dll");
    

    所以你的代码在更改后可能看起来像这样

    var directoryName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Directory");
    
    if (Directory.Exists(directoryName)) {
        var randomExt = ".random"; // generate randomly
        Directory.Move(directoryName, directoryName + randomExt)
        Directory.Delete(directoryName + randomExt, true);
    }
    Directory.CreateDirectory(directoryName);
    
    var stream = File.Create(Path.Combine(directoryName, "File")); //throws
    stream.Close();
    

    【讨论】:

    • 好的,您的解决方案有效,但它看起来像一个黑客。 Directory.Delete 方法文档明确指出该方法删除文件夹及其内容。没有任何信息表明它可能是异步的。我根本无法接受它是异步的。你能参考一些文章来证明你的意思吗?
    • 很抱歉让您失望了。要证明 Directory.Delete 使用 RemoveDirectory,您必须使用 ILSpy。可以通过msdn.microsoft.com/en-us/library/windows/desktop/… 访问 RemoveDirectory 文档。只需查看 cmets 部分。
    【解决方案3】:

    这个问题也让我感到惊讶。我的替代方案,这是一个不同的组合:

        if (Directory.Exists(directoryName))
        {
            Directory.Delete(directoryName, true);
            while (Directory.Exists(directoryName))
                Thread.Sleep(100);
        }
    
        Directory.CreateDirectory(directoryName);
    

    【讨论】:

      【解决方案4】:

      在某些情况下,如果您在文件资源管理器中打开了指定的目录,Delete 方法可能无法将其删除。

      参考:Directory.Delete Method

      【讨论】:

      • 删除成功,但结果延迟可见
      • 在 MSDN 参考中有一个Directory.Delete 将抛出IOException 的条件列表。甚至令我惊讶的是,它并没有处理这种情况(文件夹在资源管理器中打开)。但是在Remarks 部分他们提到,在某些情况下,如果您在文件资源管理器中打开了指定的目录,Delete 方法可能无法删除它。
      • 事实并非如此。目录被删除。
      猜你喜欢
      • 2020-11-05
      • 2018-08-16
      • 1970-01-01
      • 2011-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      相关资源
      最近更新 更多