使用后删除临时文件

14

我需要在我的Windows Forms .NET 3.5应用程序中使用一些临时文件。这些文件在外部应用程序中打开,可能会运行比我的程序更长的时间。

有没有最佳实践来确保这些临时文件随时清理,以避免填充用户的硬盘空间,并且不再需要的“垃圾”文件?或者甚至Windows本身是否会自动处理这个问题?

一个好的例子是任何邮件客户端:当您在任何应用程序中打开附件时,通常会将其写入一个打开的临时文件。有没有办法找出这些文件如何管理清除?

使用Google搜索显示了很多清理和调整工具,手动清理临时目录,但我不想强制用户这样做。 :-)

8个回答

28

.NET 中可以使用 TempFileCollection 类来管理一组临时文件,并使你的应用程序在退出时自动清理它们(需要注意的是它位于 CodeDom 命名空间中,有点隐藏)。显然,你不能删除任何不属于自己的文件,因为这些文件可能仍然被其他应用程序打开(删除它们可能会引发严重问题)。


临时文件集合类?热门! - George Mauer
8
确实;-) 不知道为什么这门课程如此隐秘。如果不是偶然的话,你就找不到它了... - Dirk Vollmar
哇,不再需要自己动手解决问题了,看起来微软总是在我们需要它的两年后才实现 ;) - invert
谢谢指出这个类!但是,它并没有解决 OP 的问题(临时文件可能需要比您的应用程序存在更长时间,但不是永远)。 - Darryl
2
观察Outlook如何处理临时文件(用于预览和启动附件),它们将它们放在临时文件夹中,并在Outlook关闭时尝试删除它们。在实践中与TempFileCollection的操作非常相似。 - Ian Boyd

7

清理临时文件的责任应该由创建它们的应用程序承担。这很容易做到。我使用了一个类,看起来像这样:

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

如果您需要清理另一个应用程序的临时文件,它需要一些与您的应用程序进行通信的手段。至少它应该能够提供一个信号量。但是,这样做的复杂性比让原始应用程序自己处理其文件的复杂性更大。


5

如果您试图确定性地清除临时文件类型文件夹的内容,您会冒着删除其他进程正在使用的文件的风险。Windows操作系统提供了工具,允许用户在卷的可用磁盘空间达到一定阈值时删除这些文件。

现在,如果您可以确定在使用特定临时文件后它将不再需要,那么删除该特定文件是没有任何风险的。


是的,目前我正在捕获进程的退出事件来删除不再需要的文件...那么,“鼓励”用户使用Windows磁盘清理工具是一个好的实践吗? :) - Matthias Meid

2
我们遇到了类似的文件生命周期问题 - (winforms)应用程序可以从中央存储库获取文档供用户查看,但用户关闭我们的应用程序后不应影响他们正在查看的文件。由于安全问题,文档文件需要清理,以便它们不会在系统中存在太长时间。 我们使用的解决方案是,在用户隔离存储区中创建一个以日期命名的文件夹,并将其用作今天的缓存。在应用程序关闭和启动时,我们检查以前的日期缓存文件夹并删除它们(以及其中的内容)。

1
我使用这个解决方案(相当可靠):
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();

为确保应用程序关闭或崩溃后删除所有临时文件,请执行以下操作:

TemporaryFiles.DeleteAllPreviouslyUsed();

在应用程序启动时。

1

我相信当用户注销时,它们将被删除。

回到人们每天关闭他们的电脑的日子,那可能是一个完美的解决方案。

现在,人们可能会连续数月不注销,所以依赖这一点可能不是一个好主意。

此外,如果他们关闭机器而没有关闭,则文件也不会被删除。

您可以使用文件系统监视器来监视您编写的文件,并等待一段时间的不活动(10分钟、1小时、1天或其他),然后删除该文件。

但并非所有情况都适用。有些程序可能会“打开”文件,但可能没有锁定底层文件。如果发生这种情况,那么您就无法知道何时安全地删除该文件。

然而,我认为您可以忽略这个问题。大多数人可能已经拥有了足够的硬盘空间,所以他们可能不太可能遇到这个问题。如果他们确实遇到了,我认为Windows会弹出一个低磁盘空间对话框,给他们清除临时目录的选项,这将解决问题。

更新:

我认为Windows更新会每个月重新启动用户的计算机,因此在发生这种情况时应清除临时文件。

不能保证不会出现问题,但实际上我认为这种情况应该相当罕见。

更新2:

受评论的启发,我进行了实际测试,看起来Windows在用户注销时不会删除临时文件。然而,我仍然认为在OP的情况下,这不是一个真正的问题。当它成为问题(因为磁盘空间不足)时,Windows会提示用户删除临时文件。


你想依赖于 Windows 更新吗?并且这个更新需要重新启动计算机吗?而且用户没有禁用自动更新吗? - Martin
我想说的是,如果你把东西留在临时文件夹里,这并不是什么大问题。Windows 有几种自动删除文件的方式。即使它没有自动删除,只有当磁盘空间变得很低时才会出现问题。当发生这种情况时,用户会看到一个对话框,上面写着“如何解决此问题”。 - Scott Wisniewski
在默认配置下,Windows 不会清理您的临时文件夹中的任何文件(除非在收到气球提示说明驱动器没有足够的可用磁盘空间时运行 Cleanmgr.exe,但我不会称之为自动)。 - Dirk Vollmar
顺便说一下,即使在Windows上,也有可能让您的系统运行一个月以上;-) - Dirk Vollmar
我的观点仍然是,这不重要。只有当你使用完所有磁盘空间时,或者客户注意到他的磁盘空间很低时才会成为问题,这时临时文件夹将被删除。 - Scott Wisniewski
我认为你是对的,Scott。但是查看一下我的个人资料临时目录告诉我最旧的文件只有几天的历史。可能还有另一个Windows的“秘密”功能来保持临时目录的清洁……?等我有时间了,我会去谷歌一下这个问题。 - Matthias Meid

1
在使用 ASP.NET 中的临时文件时,请使用 PAGE_DISPOSED 事件来删除页面中创建的任何临时文件。否则,您可能会与那些一直不放手直到已释放的组件发生争用问题。

0
  • 您可以创建一个临时文件,在其中可以持续写入在过程中创建的文件名,处理结束后,您可以(前提条件 - 实现IDisposable并)在操作完成后的Disponse方法中删除。

  • 另一种方法是编写独立进程,每个间隔执行清理。

  • 在文件末尾附加日期,并在当天结束时使用该日期删除,处理将生成带有新日期结尾的新文件。

  • Divo tempfilecollection类提供了一个很好的建议。

希望这有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接