Question

I'm writing this Windows Form Application in Visual Studio 2010 using C#.

There is a Execute button on the form, the user will hit the button, the program will generate some files and are stored in the Output folder (which is created by the program using Directory.CreateDirectory())

I want to create an Archive folder to save the output files from previous runs.

In the beginning of each run, I try to move the existing Output folder to the Archive folder, then create a new Output folder. Below is the function I ran to move directory.

static void moveToArchive()
{
    if (!Directory.Exists("Archive")) Directory.CreateDirectory("Archive");
    string timestamp = DateTime.Now.ToString("yyyyMMddHHmms");
    try
    {
        Directory.Move("Output", "Archive\\" + timestamp);
    }
    catch(Exception e)
    {
        Console.WriteLine("Can not move folder: " + e.Message);
    }
}

The problem I ran into confuses me a lot...

There are some times that I can successfully move the Output folder to archive, but sometimes it fails.

The error message I got from catching the exception is Access to path 'Output' is denied.

I have checked that all the files in the Output folder are not in use. I don't understand how access is denied sometimes and not all the times.

Can someone explain to me and show me how to resolve the problem?

--Edit--

After HansPassant comment, I modified the function a little to get the current directory and use the full path. However, I'm still having the same issue.

The function now looks like this:

static void moveToArchive()
{
    string currentDir = Environment.CurrentDirectory;
    Console.WriteLine("Current Directory = " + currentDir);
    if (!Directory.Exists(currentDir + "\\Archive")) Directory.CreateDirectory(currentDir + "\\Archive");
    string timestamp = DateTime.Now.ToString("yyyyMMddHHmms");
    try
    {
        Directory.Move(currentDir + "\\Output", currentDir + "\\Archive\\" + timestamp);
    }
    catch(Exception e)
    {
        Console.WriteLine("Can not move folder: " + e.Message);
    }
}

I printed out the current directory and it is just as what I was expecting, and I'm still having trouble using full path. Access to path 'C:\Users\Me\Desktop\FormApp\Output' is denied.

--Edit--

Thank you everyone for answering and commenting.

I think some of you miss this part so I'm going stress it a bit more.

The Directory.Move() sometimes work and sometimes fails.

When the function succeed, there was no problem. Output folder is moved to Archive

When the function fails, the exception message I got was Access to path denied.

Was it helpful?

Solution

Thank you all for the replies and help. I have figured out what the issue was.

It is because there was a file that's not completely closed.

I was checking the files that were generated, and missed the files the program was reading from.

All files that were generated were closed completely. It was one file I used StreamReader to open but didn't close. I modified the code and am now not having problem, so I figure that's were the issue was.

Thanks for all the comments and answers, that definitely help me with thinking and figuring out the problem.

OTHER TIPS

See http://windowsxp.mvps.org/processlock.htm

Sometimes, you try to move or delete a file or folder and receive access violation or file in use - errors. To successfully delete a file, you will need to identify the process which has locked the file. You need to exit the process first and then delete the particular file. To know which process has locked a file, you may use one of the methods discussed in this article.

Using Process Explorer - download from http://download.sysinternals.com/files/ProcessExplorer.zip

Process Explorer shows you information about which handles and DLLs processes have opened or loaded.

Download Process Explorer from Microsoft site and run the program. Click the Find menu, and choose Find Handle or DLL... Type the file name (name of the file which is locked by some process.) After typing the search phrase, click the Search button You should see the list of applications which are accessing the file.

I bumped on the same problem recently. Using PE I'd figured that only process using that particular directory was explorer.exe. I'd opened few windows with explorer, one pointing to parent directory of one that I was about to move.

It appeared, that after I visited that sub-folder and then returned (even to root level!) the handle was still being kept by explorer, so C# was not able to modify it in any way (changing flags, attributes etc.).

I had to kill that explorer window in order to made C# operate properly.

File.SetAttributes(Application.dataPath + "/script", FileAttributes.Normal);
Directory.Move(Application.dataPath + "/script", Application.dataPath + "/../script");

This fixed my problem.

Try this: If this does not solve, maybe check/change the antivirus, or the some other program is locking some file in or the folder.

    static object moveLocker = new object();
    static void moveToArchive()
    {
        lock (moveLocker)
        {
            System.Threading.Thread.Sleep(2000);  // Give sometime to ensure all file are closed.

            //Environment.CurrentDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
            string applicationPath = System.AppDomain.CurrentDomain.BaseDirectory;
            string archiveBaseDirectoryPath = System.IO.Path.Combine(applicationPath, "Archive");

            if (!Directory.Exists(archiveBaseDirectoryPath)) Directory.CreateDirectory(archiveBaseDirectoryPath);

            String timestamp = DateTime.Now.ToString("yyyyMMddHHmms");
            String outputDirectory = System.IO.Path.Combine(Environment.CurrentDirectory, "Output");
            String destinationTS = System.IO.Path.Combine(archiveBaseDirectoryPath, timestamp);
            try
            {
                Directory.Move(outputDirectory, destinationTS);                
            }
            catch (Exception ex)
            {
                Console.WriteLine("Can not move folder " + outputDirectory + " to: " + destinationTS + "\n" + ex.Message);
            }
        }
    }

I had the same problem, it failed sometimes but not all the time. I thought I'd wrap it in a Try Catch block and present the user with an Access Denied message and once I wrapped it in the Try Catch block it stopped failing. I can't explain why.

 If existingFile.FileName <> newFileName Then
    Dim dir As New IO.DirectoryInfo(existingFile.FilePath)
    Dim path As String = System.IO.Path.GetDirectoryName(dir.FullName)
    newFileName = path & "\" & newFileName

    File.SetAttributes(existingFile.FilePath, FileAttributes.Normal)
        Try
            IO.File.Move(existingFile.FilePath, newFileName)
        Catch ex As Exception

        End Try
End If

I had a similar problem. Renamed many directories in a loop when following the certain template. From time to time the program crashed on different directories. It helped to add a sleep thread before Directory.Move. I need to create some delay. But it slows down the copying process.

foreach (var currentFullDirPath in Directory.GetDirectories(startTargetFullDirectory, "*", SearchOption.AllDirectories))
            {
                var shortCurrentFolderName = new DirectoryInfo(currentFullDirPath).Name.ToLower();
                if (shortCurrentFolderName.Contains(shortSourceDirectoryName))
                {
                    // Add Thread.Sleep(1000);
                    Thread.Sleep(1000);
                    var newFullDirName = ...;
                    Directory.Move(currentFullDirPath, newFullDirName);
                }
            }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top