Deleting Temporary Files after usage

2020-05-20 08:41发布

问题:

I need to work with some temporary files in my Windows Forms .NET 3.5 application. Those files are opened in an external application that can of course be running for a longer time than my own program.

Are there any best practices to make sure these temporary files are cleaned up at any time in order to avoid filling the user's hard disk with "junk" files which aren't needed anymore? Or does even Windows kind of handle this automatically?

A nice example is any mail client: When you open an attachment in any application, it is usually written to a temporary file which is opened. Is there a way to figure out how those files manage cleanup?

Using Google has shown me many, many cleanup and tune-up tools to clean the temp directory by hand, but I'd not like to force the users to do so. :-)

Any help is appreciated.

Matthias

回答1:

If you attempt to deterministically clear the contents of a Temporary Files type folder, you risk removing files that are in use by other processes. The Windows operating system provides tools to allow users to remove those files when the volume's available disk space reaches a certain threshold.

Now, if you can determine that after you use a specific temporary file that it will no longer be needed, then there's no down-side to deleting that specific file.



回答2:

In .NET you can use the TempFileCollection class for managing a set of temporary files to be cleaned up by your application (Note that it is rather hidden in the CodeDom namespace). Obviously you can't delete any files not owned by yourself, because the files might still be opened by another application (and deleting them might cause serious issues).



回答3:

The responsibility for cleaning up temporary files ought to be on the application that created them. It is very easy. I use a class that looks something like this:

public class TempFile : IDisposable
{
    public TempFile()
    { this.path = System.IO.Path.GetTempFileName(); }

    public void Dispose()
    { File.Delete(path); }

    private string path;
    public string Path { get { return path; } }
}

If you are required to clean up another application's temporary files it needs some means of communicating with yours. At a minimum it should be able to provide a semaphore. However the complexity of doing this is greater than the complexity of just having the originating application take care of its own files.



回答4:

We have a similar file lifetime problem - the (winforms) application can fetch a document from a central repository store for the user to view, but the user should be able to close our app without it affecting the file they are viewing. Due to security concerns the document files need to be cleaned up so they aren't lying around too long.

The solution we use is to create a folder with a date-derived name in the users' isolated storage area and use that as today's cache. At application close-down and start-up we check for previous dated cache folders and delete them (and contents).



回答5:

I believe they will be deleted when the user logs out.

Back in the days when people turned off their pcs every day, that was probably a perfect solution.

Now, people can potentially go months without logging off, so it may not be a good idea to rely on that.

Also, if they turn their machine off without shutting down then the files won't get deleted either.

You could use a file system watcher that watches the file you write, and wait for some period of inactivity (10 minuites, 1 hour, 1 day, or what ever) and then delete the file.

That won't work for everything though. Some programs may have a file "open", but might not have the underlying file locked. If that happens, then you would have no way of knowing when it's safe to delete the file.

However, I'm thinking you can probably just ignore the problem. Most people probably have a surplus of hard drive space anyways, so they probably aren't likely to run into it. If they do, I think Windows pops up a low disk space dialog that gives them the option to clear their temp directory, which would solve the problem.

Update:

I think Windows Update will restart the user's computer about once a month, so the temp files should be cleared when that happens.

There's no guarantee that there won't be problems, but in practice I think it should be pretty rare.

Update 2:

Prompted by a comment, I went and actually tested this, and it looks like windows doesn't delete the temp files when the user logs out. However, I still say that in the OP's case, this isn't a real problem. When it becomes a problem (because disk space is low) Windows will prompt the user to delete temporary files.



回答6:

When using temporary files in ASP.NET, use the PAGE_DISPOSED event to delete any temporary files you created in the page. Otherwise you may end up with contention with components that do not let go until DISPOSED.



回答7:

I use this solution (quite reliable):

using System.IO;
using System.Reflection;

namespace Konard.Helpers
{
    public static partial class TemporaryFiles
    {
        private const string UserFilesListFilenamePrefix = ".used-temporary-files.txt";
        static private readonly object UsedFilesListLock = new object();

        private static string GetUsedFilesListFilename()
        {
            return Assembly.GetEntryAssembly().Location + UserFilesListFilenamePrefix;
        }

        private static void AddToUsedFilesList(string filename)
        {
            lock (UsedFilesListLock)
            {
                using (var writer = File.AppendText(GetUsedFilesListFilename()))
                    writer.WriteLine(filename);
            }
        }

        public static string UseNew()
        {
            var filename = Path.GetTempFileName();
            AddToUsedFilesList(filename);
            return filename;
        }

        public static void DeleteAllPreviouslyUsed()
        {
            lock (UsedFilesListLock)
            {
                var usedFilesListFilename = GetUsedFilesListFilename();

                if (!File.Exists(usedFilesListFilename))
                    return;

                using (var listFile = File.Open(usedFilesListFilename, FileMode.Open))
                {
                    using (var reader = new StreamReader(listFile))
                    {
                        string tempFileToDelete;
                        while ((tempFileToDelete = reader.ReadLine()) != null)
                        {
                            if (File.Exists(tempFileToDelete))
                                File.Delete(tempFileToDelete);
                        }
                    }
                }

                // Clean up
                using (File.Open(usedFilesListFilename, FileMode.Truncate)) { }
            }
        }
    }
}

Every time you need temporary file use:

var tempFile = TemporaryFiles.UseNew();

To be sure all temporary files are deleted after application closes or crashes put

TemporaryFiles.DeleteAllPreviouslyUsed();

at start of the application.



回答8:

  • you can create one temp file, in which you can keep writing the file names created during the process, at the end of processing may be you can (precondition - Implement IDisposable and) delete in the Disponse method after operation is completed.

  • Other way is write independent process which perform cleanup every interval.

  • Attache the date at the end of the file, and delete at the end of the day with that date, and process will generate new files wiht new date at the end.

  • one good suggestion given by divo tempfilecollection class.

hope it helps.