yossi yossi - 4 months ago 42
C# Question

System.IO.DirectoryNotFoundException after deleting an empty folder and recreating it

I want to copy a folder, and i want to delete destination folder first.
So I am deleting destination folder then recreate it and then copy files.
The problem is that i get the

An unhandled exception of type 'System.IO.DirectoryNotFoundException' occurred in mscorlib.dll

when trying to copy files. This is the code

static public void CopyFolder(string sourceFolder, string destFolder)
{
if (Directory.Exists(destFolder)) // check if folde exist
{
Directory.Delete(destFolder, true); // delete folder
}
Directory.CreateDirectory(destFolder); // create folder

string[] files = Directory.GetFiles(sourceFolder);
foreach (string file in files)
{
string name = Path.GetFileName(file);
string dest = Path.Combine(destFolder, name);
File.Copy(file, dest, true);
FileInfo fileinfo = new FileInfo(dest); // get file attrib
if (fileinfo.Attributes != FileAttributes.ReadOnly) // check if read only
File.SetAttributes(dest, FileAttributes.Normal);
}.......


I get the exception in this line
FileInfo fileinfo = new FileInfo(dest);
.

It seems like there is a delay in the creation of the folder and in the mean time I try to copy a file into it. Any clue, what is the problem? The full exception message:


An unhandled exception of type
'System.IO.DirectoryNotFoundException'
occurred in mscorlib.dll

Additional information: Could not find
a part of the path
'C:\Users\joe\Desktop\destfolder\.buildpath'.


SOLUTION



As it been pointed out by good people, the reason for this exception is that I try recreating the folder before the deletion process is finished.
So the solution is to add 2 lines of code after deletion:

GC.Collect();
GC.WaitForPendingFinalizers();


so the correct code will be

static public void CopyFolder(string sourceFolder, string destFolder)
{
if (Directory.Exists(destFolder)) // check if folde exist
{
Directory.Delete(destFolder, true); // delete folder
GC.Collect(); // CODE ADDED
GC.WaitForPendingFinalizers(); // CODE ADDED
}
Directory.CreateDirectory(destFolder); // create folder

string[] files = Directory.GetFiles(sourceFolder);
foreach (string file in files)
{
string name = Path.GetFileName(file);
string dest = Path.Combine(destFolder, name);
File.Copy(file, dest, true);
FileInfo fileinfo = new FileInfo(dest); // get file attrib
if (fileinfo.Attributes != FileAttributes.ReadOnly) // check if read only
File.SetAttributes(dest, FileAttributes.Normal);
}.......


This way, you wait with the creation until the deletion process is finished.
Yhanks everyone and especially Saeed.

Answer Source

You got it kinda wrong. The reason for the exception is that there's still a resource that is accessing the folder (or file).

The solution is never GC.collect() or Sleep()... That's just a work around. What you're doing is just letting the garbage collector dispose of the resource, and then giving it time to act.

The RIGHT way is to manage your own resources. Instead of a static method that you have no control on, use a using block and dispose of the resource in the end of the block. This way there's no overhead while your waiting for things that aren't under your control (GC).

Use an object that controls the resources, and the using block will dispose it at the end.

In your case, using a single DirectoryInfo object that controls that resource should work.