1

I am trying to delete a File on windows using C# File.Delete API. https://msdn.microsoft.com/en-us/library/system.io.file.delete(v=vs.110).aspx I am facing UnauthorizedAccessException with this API intermittently. Actually multiple processes/threads use this file as lock with File.Open on this file. If a file is in use I expect IOException to be thrown from underlying windows code, but at sometimes I see UnauthorizedAccessException. The process which is doing this is having an appropriate permission and it works in most of the cases but randomly I hit this issue.

More Information: The extension of the file I am using as a lock is .lck and it is always empty. It is just used for locking purpose with File.Open API. Documentation says that UnauthorizedAccessException is also thrown if the file is an executable file that is in use.

Questions: Is there a possibility that .lck is considered executable and UnauthorizedAccessException is thrown?

What else is the cause for UnauthorizedAccessException because I expect IOException if the file is being used?

Dinesh R
  • 11
  • 3
  • 1
    Is `IOException` also thrown sometimes or only `UnauthorizedAccessException` ? Did you check the `Message` and/or `InnerException` of the thrown exception to see if there's some more info ? (from msdn : *To find the reasons for the exception, examine the text of the exception object's Message property*) – Rafalon Nov 13 '17 at 11:58
  • Standard reason is fumbling the path you pass to File.Delete(), passing the directory instead of the file. Running the program with a user account that does not have the file delete right is the other. Not exactly random reasons. Non-standard and random-enough reasons tend to be explained by the kind of shrink-wrapped malware that programmers voluntarily install. Always do favor a named mutex instead. – Hans Passant Nov 13 '17 at 13:20

1 Answers1

0

Internally the File.Delete function invokes the DeleteFile function of the Win32 API.

The documentation says:

If an application attempts to delete a file that does not exist, the DeleteFile function fails with ERROR_FILE_NOT_FOUND. If the file is a read-only file, the function fails with ERROR_ACCESS_DENIED.

and below:

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.

The ERROR_ACCESS_DENIED code than leads to an UnauthorizedAccessException.

So there are still at least one write handle on the file active.


In general it is a bad idea to use file handles for synchronizing processes. A better way for solving this problem would be to use a named EventWaitHandle or named Mutex (See Synchronizing 2 processes using interprocess synchronizations objects - Mutex or AutoResetEvent for mor information)

For example execute in 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();
    }
}

and in 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 will then wait until Process2 has released the mutex and vice versa.

fboers
  • 126
  • 8