Question

Consider this simple program:

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

This works fine while you simply execute this program. The strange thing happens if you browse that Directory in windows explorer and then run. In this case I get UnautorizedAccessException "Access to the path 'C:\Users\rfurman\AppData\Roaming\Directory\File' is denied."

If this is strange then execute this with the same conditions:

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

This program prints True if Directory is open in explorer.

What I would like to know is why this happens and how to defend against such situation.

I use windows 7 and .net 4.

Was it helpful?

Solution

Directory.Delete internally uses RemoveDirectory win api in Kernel32. What RemoveDirectory does is "to mark directory for deletion". Directory is deleted when last handle of that directory is closed. I believe this means "after explorer left that folder"

In my computer this situation does not occur, so I cannot test but I suspect there may be a way for you. NT based systems sometimes allows renaming of files and directories even if they are open. I don't know exact cases this is allowed, but I used this to rename loaded dll files and write new ones like this:

File.Rename(@"C:\App\test.dll", @"C:\App\test.dll");
File.Copy(@"C:\App\Update\test.dll-v1.1", @"C:\App\test.dll");

So your code may look like this after change

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

OTHER TIPS

This is somewhat of a duplicate: Bizarre directory delete behaviour on SSD drive

The explorer is just causing a slightly longer delay in the folder delete. Deleting a directory is not 'exactly' a synchronous operation. The directory is marked for deletion but the actual delete may lag a bit.

AFAIK this has been around as long as NTFS (win2k/Xp).

This problem surprised me as well. My alternative, which is a different kludge:

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

    Directory.CreateDirectory(directoryName);

In some cases, if you have the specified directory open in File Explorer, the Delete method may not be able to delete it.

Reference: Directory.Delete Method

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top