Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Deleting Folders is a Risky Business

4.94/5 (19 votes)
14 Oct 2016CPOL 54.4K  
Deleting folder programmatically is extremely dangerous. It can erase your system.

Introduction

Deleting folder programmatically is extremely dangerous. It is enough for somebody else to change a configuration file or constant variable including the target folder's name to, say C:\, and that's it: the workstation is paralyzed!

The following suggested methods are to prevent such a situation. Their aim is to wrap the low level, possibly recursive file system operation with the necessary validation and clear facade - look twice, delete once.

Delete Temporary Directory Created by Current User (Non recursive!)

C#
/// <summary>
/// carefully remove directory and its files
/// verify the directory is located under the %temp%
/// and it is not e.g. C:\
/// </summary>
/// <param name="dir"></param>

public static void DeleteTempDirShallow(string dir)
{
    // check if it is an invalid directory path,
    // e.g. a disk drive or just a bad string

    if (! Directory.Exists(dir)) return;
 
    DirectoryInfo userTempDirInfo = new DirectoryInfo(Path.GetTempPath());
    DirectoryInfo dirInfo = new DirectoryInfo(dir);
 
    if (dirInfo.FullName.Contains(userTempDirInfo.FullName))
    {
        foreach (FileInfo file in dirInfo.GetFiles())
            file.Delete();
 
        dirInfo.Delete(); // just clean up the empty dir
    }
}

Delete Temporary Directory Created by Current User (Recursive!)

C#
public static void DeleteTempDirRecursive(string dir)
{
    // check if it is an invalid directory path,
    // e.g. a disk drive or just a bad string
    if (! Directory.Exists(dir)) return;
 
    DirectoryInfo userTempDirInfo = new DirectoryInfo(Path.GetTempPath());
    DirectoryInfo dirInfo = new DirectoryInfo(dir);
 
    if (dirInfo.FullName.Contains(userTempDirInfo.FullName))
    {
        dirInfo.Delete(recursive: true);
    }
}

Do I Try to Delete Any Root or System Folder?

C#
static List<string> systemDirs = new List<string>
{
    Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles),
    Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86),
    Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms),
    Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu),
    Environment.GetFolderPath(Environment.SpecialFolder.CommonStartup),
    Environment.GetFolderPath(Environment.SpecialFolder.Fonts),
    Environment.GetFolderPath(Environment.SpecialFolder.NetworkShortcuts),
    Environment.GetFolderPath(Environment.SpecialFolder.PrinterShortcuts),
    Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
    Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
    Environment.GetFolderPath(Environment.SpecialFolder.Resources),
    Environment.GetFolderPath(Environment.SpecialFolder.StartMenu),
    Environment.GetFolderPath(Environment.SpecialFolder.Startup),
    Environment.GetFolderPath(Environment.SpecialFolder.System),
    Environment.GetFolderPath(Environment.SpecialFolder.SystemX86),
    Environment.GetFolderPath(Environment.SpecialFolder.Templates),
    Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
    Environment.GetFolderPath(Environment.SpecialFolder.Windows),
};
 
/// <summary>
/// check if the argument dir is a disk drive,
/// is a system (sub-)folder
/// and should not be erased
/// </summary>
/// <param name="dir"></param>
/// <returns></returns>
public static bool IsSystemOrRootDir(string dir)
{
    // check if it is an invalid directory path,
    // or just a bad string
    if (! Directory.Exists(dir)) return true;
 
    DirectoryInfo dirInfo = new DirectoryInfo(dir);
 
    // is it a root (disk drive)?
    if (dirInfo.Parent == null) return true;
 
    // is it a system (sub-)folder?
    return systemDirs.Any(
                 sysDir => dirInfo.FullName
                           .IndexOf(sysDir, StringComparison.OrdinalIgnoreCase) >= 0);
}

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)