tags:

views:

2706

answers:

5

Hello all.
What are a good way to ensure that a tempfile is deleted if my application closes or crashes? Ideally I would like to obtain a tempfile, use it and then forget about it.

Right now I keep a list of my tempfiles and delete them with an eventhandler that triggers on Application.ApplicationExit.

Is there a better way?

+3  A: 
csl
The destructor is commonly used to release handles and resources on a per class basis. I imagine that you could use it to delete files, but that should be really be handled by the application code that created them.
StingyJack
Noob question: Does it have to be deterministic? To my knowledge, deterministic means that you do not know exactly WHEN it will run, but normally you can be sure that it WILL run (unless you yank the power cord of course) - or am I wrong here?
Michael Stum
A: 

Its nice to see that you want to be responsible, but if the files aren't huge (>50MB) you would be in line with everyone (MS included) in leaving them in the temp directory. Disk space is abundant.

As csl posted, the GetTempPath is the way to go. Users who are short on space will be able to run disk cleanup and your files (along with everyone else's) will be cleaned up.

StingyJack
Personally I think a temp file is a temp file, and should be destroyed as soon as it's no longer needed. I hate my disk being cluttered with all kinds of trash. Shameful that no-one (MS included) cares about my computer's state...
Agreed, and RAII would solve that nicely.
csl
Understood, It's commendable to try, but my point is that if you cant get everything, its not going to be bad.
StingyJack
Agreed.. if for whatever reason you can't clean up all files, they'd better be in the temp directory then anywhere else.
+6  A: 

Nothing is guaranteed if the process is killed prematurely, however, I use "using" to do this..

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

    public TempFile(string path)
    {
        if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
        this.path = path;
    }
    public string Path
    {
        get
        {
            if (path == null) throw new ObjectDisposedException(GetType().Name);
            return path;
        }
    }
    ~TempFile() { Dispose(false); }
    public void Dispose() { Dispose(true); }
    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            GC.SuppressFinalize(this);                
        }
        if (path != null)
        {
            try { File.Delete(path); }
            catch { } // best effort
            path = null;
        }
    }
}
static class Program
{
    static void Main()
    {
        string path;
        using (var tmp = new TempFile())
        {
            path = tmp.Path;
            Console.WriteLine(File.Exists(path));
        }
        Console.WriteLine(File.Exists(path));
    }
}

Now when the TempFile is disposed or garbage-collected the file is deleted (if possible). You could obviously use this as tightly-scoped as you like, or in a collection somewhere.

Marc Gravell
It's not often you see a proper place to use an empty catch block.
Robert Rossney
I'll probably implement a variant of this. It's straight forward and easy to understand.
Nifle
+2  A: 

You could P/Invoke CreateFile and pass the FILE_FLAG_DELETE_ON_CLOSE flag. This tells Windows to delete the file once all handles are closed. See also: Win32 CreateFile docs.

David Grant
A: 

You could launch a thread on startup that will delete files that exist when they "shouldn't" to recover from your crash.

Austin Salonen