Question

Quels sont les bons moyens de garantir la suppression d’un fichier temporaire si mon application se ferme ou se bloque? Idéalement, j'aimerais obtenir un fichier temporaire, l'utiliser et ensuite l'oublier.

À l'heure actuelle, je conserve une liste de mes fichiers temporaires et les supprime à l'aide d'un gestionnaire d'événements qui se déclenche sur Application.ApplicationExit.

Y a-t-il un meilleur moyen?

Était-ce utile?

La solution

Rien n'est garanti si le processus est tué prématurément. Toutefois, j'utilise " en utilisant ". faire ceci ..

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));
    }
}

Maintenant, lorsque le TempFile est supprimé ou récupéré, le fichier est supprimé (si possible). Vous pouvez évidemment utiliser cela aussi étroitement que vous le souhaitez, ou dans une collection quelque part.

Autres conseils

Pensez à utiliser l'indicateur FileOptions.DeleteOnClose:

using (FileStream fs = new FileStream(Path.GetTempFileName(),
       FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None,
       4096, FileOptions.RandomAccess | FileOptions.DeleteOnClose))
{
    // temp file exists
}

// temp file is gone

Vous pourriez lancer / invoquer CreateFile et transmettez l'indicateur FILE_FLAG_DELETE_ON_CLOSE . Cela indique à Windows de supprimer le fichier une fois que tous les descripteurs sont fermés. Voir aussi: Win32 CreateFile docs .

J'utiliserais la classe .NET TempFileCollection , car elle est intégrée, disponible dans les anciennes versions de .NET et implémente l'interface IDisposable et nettoie donc après lui-même si utilisé par exemple en conjonction avec le mot-clé "utilisant" " .

Voici un exemple d'extraction de texte à partir d'une ressource incorporée (ajoutée via les pages de propriétés du projet - > Ressources, comme décrit ici: Comment incorporer un fichier texte dans un assemblage .NET? , puis définissez-le sur " EmbeddedResource "dans le répertoire paramètres de propriétés du fichier incorporé).

    // Extracts the contents of the embedded file, writes them to a temp file, executes it, and cleans up automatically on exit.
    private void ExtractAndRunMyScript()
    {
        string vbsFilePath;

        // By default, TempFileCollection cleans up after itself.
        using (var tempFiles = new System.CodeDom.Compiler.TempFileCollection())
        {
            vbsFilePath= tempFiles.AddExtension("vbs");

            // Using IntelliSense will display the name, but it's the file name
            // minus its extension.
            System.IO.File.WriteAllText(vbsFilePath, global::Instrumentation.Properties.Resources.MyEmbeddedFileNameWithoutExtension);

            RunMyScript(vbsFilePath);
        }

        System.Diagnostics.Debug.Assert(!File.Exists(vbsFilePath), @"Temp file """ + vbsFilePath+ @""" has not been deleted.");
    }

Je ne suis pas principalement un programmeur C #, mais en C ++, j'utiliserais RAII . pour ça. Il y a astuces sur l'utilisation en ligne d'un comportement semblable à RAII en C # , mais la plupart semblent utiliser le finaliseur & # 8212; qui n'est pas déterministe.

Je pense que certaines fonctions du SDK Windows permettent de créer des fichiers temporaires, mais je ne sais pas s'ils sont automatiquement supprimés à la fin du programme. Il existe la fonction GetTempPath , mais les fichiers il n’existe que lorsque vous vous déconnectez ou que vous redémarrez, IIRC.

P.S. La la documentation de C # destructor indique que vous pouvez et devez y publier des ressources, qui Je trouve un peu bizarre. Si tel est le cas, vous pouvez simplement supprimer le fichier temporaire dans le destructeur, mais là encore, il se peut que cela ne soit pas complètement déterministe.

C’est agréable de voir que vous voulez être responsable, mais si les fichiers ne sont pas énormes (> 50 Mo), vous pouvez laisser tout le monde (MS inclus) les laisser dans le répertoire temporaire. L’espace disque est abondant.

Comme csl l'a écrit, GetTempPath est la solution. Les utilisateurs à court d’espace pourront exécuter le nettoyage du disque et vos fichiers (ainsi que ceux des autres) seront nettoyés.

J'utilise une solution plus fiable:

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)) { }
            }
        }
    }
}

Chaque fois que vous avez besoin d'un fichier temporaire:

var tempFile = TemporaryFiles.UseNew();

Pour vous assurer que tous les fichiers temporaires sont supprimés après la fermeture ou le blocage de l'application

TemporaryFiles.DeleteAllPreviouslyUsed();

au début de l'application.

Vous pouvez lancer au démarrage un thread qui supprimera les fichiers existants alors qu'ils ne devraient pas " " pour récupérer de votre crash.

Si vous créez une application Windows Forms, vous pouvez utiliser ce code:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        File.Delete("temp.data");
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top