在什么情况下,Windows File.Delete API会抛出UnauthorizedAccessException,尤其是在文件正在使用时?

时间:2017-11-13 11:48:43

标签: c#

我正在尝试使用C#File.Delete API删除Windows上的文件。 https://msdn.microsoft.com/en-us/library/system.io.file.delete(v=vs.110).aspx 我间歇地使用此API面临UnauthorizedAccessException。实际上,多个进程/线程使用此文件作为此文件上的File.Open锁。如果文件正在使用中,我希望从底层的Windows代码中抛出IOException,但有时我会看到UnauthorizedAccessException。执行此操作的过程具有适当的权限,并且在大多数情况下都适用,但随机我遇到了此问题。

更多信息: 我用作锁的文件的扩展名是.lck,它总是为空的。它仅用于File.Open API的锁定目的。 文档说如果文件是正在使用的可执行文件,也会抛出UnauthorizedAccessException。

问题: 是否有可能将.lck视为可执行文件并抛出UnauthorizedAccessException?

UnauthorizedAccessException的原因是什么,因为如果正在使用该文件,我期望IOException?

1 个答案:

答案 0 :(得分:0)

File.Delete函数在内部调用Win32 API的DeleteFile函数。

文档说:

  

如果应用程序尝试删除不存在的文件,则DeleteFile函数将失败并显示ERROR_FILE_NOT_FOUND。 如果文件是只读文件,则函数将失败,并显示ERROR_ACCESS_DENIED

及以下:

  

DeleteFile函数在关闭时标记要删除的文件。 因此,在关闭文件的最后一个句柄之前不会发生文件删除。随后调用CreateFile以打开文件失败并显示ERROR_ACCESS_DENIED

ERROR_ACCESS_DENIED代码导致UnauthorizedAccessException

因此文件上至少有一个写句柄处于活动状态。

通常,使用文件句柄来同步进程是个坏主意。解决此问题的更好方法是使用名为EventWaitHandle或命名为Mutex(请参阅Synchronizing 2 processes using interprocess synchronizations objects - Mutex or AutoResetEvent获取mor信息)

例如,在 Process1 中执行:

while (true)
{
    using (var mutex = new Mutex(false, "THIS_IS_THE_UNIQUE_NAME_OF_THE_MUTEX"))
    {
        if (!mutex.WaitOne(0))
        {
            Console.WriteLine($"Process {Process.GetCurrentProcess().Id} waits");
            mutex.WaitOne();
        }
        Console.Write($"Process {Process.GetCurrentProcess().Id} has entered protected area...");

        Thread.Sleep(1000); // simulate work

        Console.WriteLine("and is about to leave!");
        mutex.ReleaseMutex();
    }
}

Process2

using (var mutex = new Mutex(false, "THIS_IS_THE_UNIQUE_NAME_OF_THE_MUTEX"))
{
    mutex.WaitOne();    
    Thread.Sleep(5000); // simulate work on different process
    mutex.ReleaseMutex();
}

Process1 将等待 Process2 释放互斥锁,反之亦然。