是什么原因导致CreateDirectory返回ERROR_ACCESS_DENIED?

时间:2010-08-25 22:08:43

标签: winapi directory getlasterror

another question中,我们确定是的,CreateDirectory偶尔会因未记录的GetLastErrorERROR_ACCESS_DENIED而失败,并且正确处理这种情况的方法可能是再试一次。实现这样的算法很容易,但是当你不知道如何重现它时,测试它并不容易。

我不需要理论为何会发生这种情况。它可能是Windows中的一个错误,是的。它也可能是设计上的。最终,在这一点上,没关系,因为微软发布了这种行为,我必须应对。

我也不需要解释多任务操作系统理论以及Windows如何实现它。我以编写系统软件为生。我完全不懂。

我现在需要的是一种重现失败的可靠方法,因此我可以编写一个测试用例来处理代码。这是我到目前为止所尝试的内容:

  • 我编写了测试程序P1,它缓慢而重复地枚举了潜在父母的内容。同样,我编写了测试程序P2,它除了反复尝试删除和创建将成为父级的目录之外什么都不做。我认为长时间打开枚举可能会使问题更容易发生。单独运行P2会偶尔出现故障(大约每隔几分钟约10毫秒)。同时运行P1和P2似乎不会使故障更频繁或更长。

  • 我同时运行了两个P2实例,这似乎不会使故障更频繁或更长。

  • 我修改了P2,这样它就可以创建除目录之外的文件,并且在P1的同时运行它似乎不会使故障更频繁或更长。

  • 我同时运行P1和多个具有不同参数的P2实例,这似乎不会使故障更频繁或更长。

  • 我编写了测试程序P3,它将项目移入和移出潜在的父项,并在P2的同时运行P3,这似乎不会使故障更频繁或更长。

还有其他想法吗?

2 个答案:

答案 0 :(得分:1)

首先让我仔细检查一下,我理解这个问题。如果您运行类似下面的代码片段,那么您最终会失败,对吗?

while (true)
{
    System.IO.Directory.CreateDirectory( ".\\FooDir" );
    System.IO.Directory.Delete( ".\\FooDir" );
}

如果您的应用程序是在系统上运行的唯一具有对该文件打开的句柄的应用程序,则此感觉就像一个错误。所以了解操作系统版本会有所帮助。

另一方面,如果系统中还有其他东西让手柄保持打开一段时间,那么这是否是一个错误会变得更加模糊。尝试盲目浏览文件和目录的事物数量可能会让您大吃一惊。例如,一个天真的索引器可能正在进入该目录,枚举它,寻找要索引的文件等等 - 如果你与他发生碰撞,那就是blammo。一个类似的天真的反病毒过滤器,或其他一些文件系统过滤器,也可能会戳它(在这种情况下,它仍然感觉像一个错误)。

我们在操作系统中做的很少的事情是尝试提供这些方式的服务以避开您的方式。如果关闭任何反病毒,任何反恶意软件,你是否会关闭索引器?我们可以从那里开始,希望我们会发现新的位已经修复了(我知道这个陈述有很多假设)。

另一个相对有趣的琐事是,ERROR_ACCESS_DENIED是一个Win32错误,它是从系统中的多个底层状态映射的(例如,请参阅this article)。因此,如果我们可以深入挖掘一下,我们可以找出文件系统试图告诉应用程序的内容(如果它不仅仅是访问被拒绝)。

我们最终可能会谈到你是否可以在野外假设你的应用程序是你的文件和目录唯一的东西。你可以猜到那个人会去哪里。

答案 1 :(得分:1)

我猜赌你的枚举/删除/创建会导致句柄出现一些同步问题。如果CreateDirectory类似于CreateFile(并且我会假设它背后的逻辑将被共享),那么你会看到与CreateFile类似的行为:

  

如果您在一个文件上调用CreateFile   正在等待删除的结果   以前调用DeleteFile,   功能失败。操作系统   延迟文件删除直到所有句柄   到文件已关闭。 GetLastError函数   返回ERROR_ACCESS_DENIED。