文件访问和探索器窗口的奇怪exception

考虑这个简单的程序:

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."拒绝"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。

Directory.DeleteKernel32内部使用RemoveDirectory win api。 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(); 

这有点重复: SSD驱动器上的奇怪目录删除行为

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

AFAIK和NTFS(win2k / Xp)一样长。

这个问题也让我感到惊讶。 我的替代品,这是一个不同的kludge:

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

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

参考: Directory.Delete方法