2012-10-09 24 views
1

奇怪的例外考虑这个简单的程序:文件访问和explorator窗口

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(); 
} 

这个程序打印True如果Directory在资源管理器中打开。

我想知道的是为什么发生这种情况以及如何防止这种情况。

我使用Windows 7和.NET 4

+0

“如果你浏览该目录”是什么意思? – Luftwaffe

+0

@Lufftwaffe:在Windows资源管理器中打开该文件夹 – Rafal

+0

,这样你的意思是..该文件夹保持在资源管理器中打开..对吗? – Luftwaffe

回答

2

Directory.Delete内部使用的Kernel32RemoveDirectory赢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(); 
+0

确定您的解决方案有效,但它会作为黑客攻击。 Directory.Delete方法文档明确指出该方法删除文件夹及其内容。没有任何信息可能是异步的。我简直不能接受它是异步的。你能参考一些证明你在暗示什么的文章吗? – Rafal

+0

对不起,失望。为了证明'Directory.Delete'使用RemoveDirectory,你必须使用ILSpy。 RemoveDirectory文档可以访问在http://msdn.microsoft.com/en-us/library/windows/desktop/aa365488(v=vs.85).aspx。只需看看评论部分。 – edokan

-1

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

参考:Directory.Delete Method

+0

....但它应该抛出一个'IOException'? – ulrichb

+0

删除成功,但延迟结果是可观察的 – Rafal

+0

在MSDN Reference中有一个列表,其中Directory.Delete会抛出IOException。甚至令我惊讶的是,这个条件(文件夹在资源管理器中打开)不是由它处理的。但在“备注”一节中,他们提到在某些情况下,如果您在文件资源管理器中打开指定的目录,则Delete方法可能无法将其删除。 – Luftwaffe

3

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

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

AFAIK这一直围绕只要NTFS(WIN2K/XP)。

0

这个问题也让我感到惊讶。我的替代方案,这是一个不同的kludge:“如果你浏览该目录”是什么意思?

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

    Directory.CreateDirectory(directoryName);