10

Here is my code that I am using to extract a zip file making sure the target dir doesn't have any dirty files in it

internal void UnzipProject()
{
    if (Directory.Exists(SourceDir))
        Directory.Delete(SourceDir, true);

    if (File.Exists(CodeZipFile))
    {
        Directory.CreateDirectory(SourceDir); // fails here
        ZipFile.ExtractToDirectory(CodeZipFile, SourceDir);
    }
}

Sometime Directory.CreateDirectory(SourceDir) fails to create new dir and I get exception on next line but if I step back and retry dir creation, it works. Exactly same pattern is repeated on next execution.

EDIT
Here is the exception that actually is about dir not having been created, I can see the src dir doesn't exist:

System.UnauthorizedAccessException was unhandled
  HResult=-2147024891
  Message=Access to the path '(...MyPath...)\src\MySolution.sln' is denied.
  Source=mscorlib
  StackTrace:
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
       at System.IO.Compression.ZipFileExtensions.ExtractToFile(ZipArchiveEntry source, String destinationFileName, Boolean overwrite)
       at System.IO.Compression.ZipFileExtensions.ExtractToDirectory(ZipArchive source, String destinationDirectoryName)
       at System.IO.Compression.ZipFile.ExtractToDirectory(String sourceArchiveFileName, String destinationDirectoryName, Encoding entryNameEncoding)
       at System.IO.Compression.ZipFile.ExtractToDirectory(String sourceArchiveFileName, String destinationDirectoryName)
........
6
  • 7
    What is the exception that you get "sometimes"
    – Habib
    Commented Jan 28, 2016 at 18:34
  • How frequently do you run this method? Once per hour, once per minute, 1000 times per second?
    – Oxoron
    Commented Jan 28, 2016 at 18:39
  • Running this method, on application startup only. In production it may be recalled once in many minutes
    – WSK
    Commented Jan 28, 2016 at 18:41
  • Interesting to see, people are down voting this question? Would you please share the reason?
    – WSK
    Commented Jan 28, 2016 at 18:49
  • 1
    1) Is there any antivirus running? Can you disable it and retry? 2) Is that happening on a network share or on a regular local folder? 3) Could you please try with AlphaFS (library that replaces all IO namespace while fixing lots of bugs like long paths, etc).
    – drizin
    Commented Jan 28, 2016 at 19:00

5 Answers 5

17

Had this problem under Windows 7, .Net 4.0, VS2010. It would appear Directory.Delete() is not synchronous so the issue is timing. I'm guessing Directory.CreateDirectory() does not fail because the existing folder is marked for deletion. The new folder is then dropped as Directory.Delete() finishes.

I found this works consistently:

if (Directory.Exists(myPath))
  {
  Directory.Delete(myPath, true);
  while (Directory.Exists(myPath))
    System.Threading.Thread.Sleep(10);
  }

Directory.CreateDirectory(myPath);
4
  • It's crazy that this method is asynchronous! Thanks for your input that helped me solve this issue. Commented Dec 4, 2020 at 15:56
  • Again and again I cannot believe it, but yes, this is async. crazy. Confirmed from here
    – citykid
    Commented Sep 18, 2021 at 13:32
  • 1
    Well, yeah, the documentation on the Win32 RemoveDirectory API says The RemoveDirectory function marks a directory for deletion on close. Therefore, the directory is not removed until the last handle to the directory is closed., so if there's anything keeping a handle to that directory open, it won't be deleted, yet.
    – Tom Lint
    Commented Mar 1, 2022 at 13:56
  • Thanks for that @Tom Lint. Good to know I guessed right.
    – sthames42
    Commented Mar 1, 2022 at 14:54
4

The error is actually in the exception already.

System.UnauthorizedAccessException was unhandled

You need to add codes to check / verify that user has access to the folder.

4
  • Shouldn't be access issue, as it works on retry. Moreover, how can I check the access when src dir doesn't exist at all at the the time of having exception?
    – WSK
    Commented Jan 28, 2016 at 18:45
  • Your retry logic won't have anything to do with it. With access @Batuta rather means permissions Commented Jan 28, 2016 at 18:47
  • Sorry for confusion. By saying "retry" I meant to step back in debugger and re-executing this line of code again, in same application run.
    – WSK
    Commented Jan 28, 2016 at 19:01
  • 1
    You really need to combine Batuta and Twilight's answers. You need to put the call to Directory.Delete() in a try-catch block. If the exception is UnauthorizedAccessException, your program should display an error and stop. But you also need to account for long-running deletes. You're deleting a folder, which means all of the files in it have to be deleted before the folder can be removed. Commented Jan 28, 2016 at 19:04
3

Thank you all for helping me resolve this issue. Problem was to create a dir just after calling its delete. In my case deleted dir was empty but probably due to file system delays, it became inaccessible before fully deleting. I am sharing the solution, for others facing same issue:

internal void UnzipProject()
{
    if (Directory.Exists(SourceDir))
    {
        DirectoryInfo di = new DirectoryInfo(SourceDir);

        foreach (FileInfo file in di.GetFiles())
            file.Delete();

        foreach (DirectoryInfo dir in di.GetDirectories())
            dir.Delete(true);
    }

    if (File.Exists(zipFile))
        ZipFile.ExtractToDirectory(zipFile, SourceDir);

    else
    {
        if (Directory.Exists(SourceDir))
            Directory.Delete(SourceDir, true);
    }
}
0
1

I have experienced that behavior myself. If I am not mistaken, it happens because the Directory.Delete is still working trying to delete the directory while at the same time the Directory.CreateDirectory is trying to recreate it. The CreateDirectory will fail, because the system has that resource still locked for deletion.

I have avoided this problem by introducing a slight delay between the call to Delete and the call to CreateDirectory. Another option I remember having used was to rename the directory, then delete it. For example, if the original directory was called MyApp, I would rename it to DeleteMe and then delete that directory. CreateDirectory should be able to create the MyApp directory, since that doesn't exist anymore.

0

My colleague got this error on frequent rewriting of the files. He told that Fyle System is slow. If you have the same problem, you try to create a folder which is not deleted yet.

Try to repeat your method once on UnauthorizedAccessException, or\and add Thread.Sleep(100) after Directory.Delete.

1
  • In my case, directory never already exist so not being deleted.
    – WSK
    Commented Jan 28, 2016 at 19:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.