Geekender
Geekender

Reputation: 809

Deleting files in use

I created a simple program to delete temporary files in C# (for fun, not a major project) and am running into locked files (in use) issues. How do you normally either exclude those files? For reference I am receiving the error:

The process cannot access the file 'ExchangePerflog_8484fa31c65c7a31cfcccd43.dat' because it is being used by another process.

Code:

static void Main(string[] args)
    {
        string folderPath = string.Empty;
        folderPath = System.Environment.GetEnvironmentVariable("temp");
        deleteFilesInDirectory(folderPath);
    }

    public static void deleteFilesInDirectory(string folderPath) 
    {

        try
        {
            var dir = new DirectoryInfo(folderPath);
            dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly;
            dir.Delete(true);
            MessageBox.Show(folderPath + " has been cleaned.");
        }
        catch (System.IO.IOException ex)
        {
            MessageBox.Show(ex.Message); 
            return;

        } 
    }     

Upvotes: 29

Views: 93392

Answers (6)

Martin
Martin

Reputation: 3472

Using dknaack's code. This worked in my case.

FileInfo file = new FileInfo("xyz.txt");
try
{
    for (int tries = 0; IsFileLocked(file) && tries < 5; tries++)
        Thread.Sleep(1000);
    file.Delete();
}
catch (IOException exception)
{
    Console.WriteLine(string.Format("File locked: {0}", exception);
}

Upvotes: 3

Bartosz Gawron
Bartosz Gawron

Reputation: 187

Well I have run into similar problems. When you try to remove directory shortly after removing file you have to force GC to release the file handle from current thread

public void DisposeAfterTest(string filePath)
    {

        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }

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

        if (Directory.Exists(this.TempTestFolderPath))
        {
            Directory.Delete(this.TempTestFolderPath, true);
        }

    }

Upvotes: 10

Jimmy
Jimmy

Reputation: 113

The below code will delete the files from a directory and all its sub-directories excluding the locked files and gets the list of the files that are not deleted. You can change the SearchOption to TopDirectoryOnly if you consider only the current directory.

string []files = Directory.GetFiles(dirPath,"*.*", SearchOption.AllDirectories); //this gets the files in all subdirectories as well
List<string> lockedFiles = new List<string>();
foreach(string file in files) 
{    
    try    
    {        
        file.Delete();    
    }    
    catch (IOException)    
    {        
        lockedFiles.Add(file);    
    }
}

Upvotes: 0

Aravindhkumar
Aravindhkumar

Reputation: 235

Try the following code. Just add two lines before file deletion:

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

Upvotes: 16

dknaack
dknaack

Reputation: 60556

Description

There is no way to delete a file that is currently in use by another process. But you can wait till the file is not locked.

Check in a while loop till the file is unlocked with this method

protected virtual bool IsFileLocked(FileInfo file)
{
    FileStream stream = null;

    try
    {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException)
    {
        //the file is unavailable because it is:
        //still being written to
        //or being processed by another thread
        //or does not exist (has already been processed)
        return true;
    }
    finally
    {
        if (stream != null)
            stream.Close();
    }

    //file is not locked
    return false;
}

Sample

FileInfo file = new FileInfo("PathToTheFile");
while (IsFileLocked(file))
    Thread.Sleep(1000);
file.Delete();

Update

If you want to skip locked files you can do this.

//
var dir = new DirectoryInfo(folderPath);
foreach(var file in dir.GetFiles()) {
    try
    {
        file.Delete();
    }
    catch (IOException)
    {
        //file is currently locked
    }
}

Upvotes: 23

Rob P.
Rob P.

Reputation: 15091

I don't believe there is any way you can know in advance if the file is in use or not. You could try to get an exclusive lock on the file; but then you'd just be trading one exception for another.

If these are files you are opening, see if you can't do a better job of closing them. If it's more complicated than that - you could maintain a 'to delete list' and continue to retry the delete until it is successful (on another thread with a concurrent collection maybe).

I also don't believe there is anyway to forcefully delete an in-use file.

Upvotes: 1

Related Questions