Robust directory deletion in .net

I am surprised how often a simple directory delete can fail. I should just have to call Directory.Delete http://msdn.microsoft.com/en-us/library/fxeahc5f.aspx

Directory.Delete(pathToDirectory, true)

Assuming I have the appropriate permissions to perform this action and no files are locked it should just work, right? Well it turns out this is not the case. There are several issues that can prevent the deletion of a directory. For example

  • Long Paths
  • Zero length file names
  • Corrupted File system

Using the big hammer to delete a directory

Robocopy is much more robust when it comes to performing actions on the file system. It will happily perform actions that are not possible in .net and often not possible in explorer. So I use a small wrapper around robocopy that will perform a directory delete. It creates an empty temp directory and then uses robocopy’s mirror function to overwrite the contents of the target directory. This effectively deletes the contents of the target directory.

public static class RoboDelete
{
    public static void Delete(string path)
    {
        DirectoryInfo emptyTempDirectory = null;

        try
        {
            var tempDirPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            emptyTempDirectory = Directory.CreateDirectory(tempDirPath);
            using (var process = StartProcess(path, emptyTempDirectory))
            {
                process.WaitForExit();
            }
            Directory.Delete(path);
        }
        finally
        {
            if (emptyTempDirectory != null)
            {
                emptyTempDirectory.Delete();
            }
        }
    }

    static Process StartProcess(string path, DirectoryInfo emptyTempDirectory)
    {
        // /W:n :: Wait time between retries: default is 30 seconds.
        // /R:n :: number of Retries on failed copies: default 1 million.
        // /FFT :: assume FAT File Times (2-second granularity).
        // /MIR :: MIRror a directory tree (equivalent to /E plus /PURGE).
        // /NFL :: No File List - don't log file names.
        var arguments = string.Format("\"{0}\" \"{1}\" /W:1  /R:1 /FFT /MIR /NFL", emptyTempDirectory.FullName, path.TrimEnd('\\'));
        var startInfo = new ProcessStartInfo("robocopy")
                            {
                                Arguments = arguments,
                                WindowStyle = ProcessWindowStyle.Hidden,
                                CreateNoWindow = true
                            };
        return Process.Start(startInfo);
    }
}
Posted by: Simon Cropp
Last revised: 24 Dec, 2011 05:24 AM History

Comments

No comments yet. Be the first!

No new comments are allowed on this post.