我需要在Windows Forms .NET 3.5应用程序中使用一些临时文件。 这些文件在外部应用程序中打开,当然可以运行比我自己的程序更长的时间。
是否有任何最佳做法,以确保这些临时文件在任何时候被清理,以避免用不再需要的“垃圾”文件填充用户的硬盘? 还是甚至Windows的那种自动处理呢?
一个很好的例子是任何邮件客户端:当您在任何应用程序中打开附件时,通常会将其写入打开的临时文件。 有没有办法找出这些文件如何pipe理清理?
使用Google向我展示了许多清理和调整工具来手动清理临时目录,但我不想强迫用户这样做。 🙂
任何帮助表示赞赏。
马蒂亚斯
如果您尝试确定性地清除Temporary Files类型文件夹的内容,则可能会删除其他进程正在使用的文件。 Windows操作系统提供的工具允许用户在卷的可用磁盘空间达到特定阈值时删除这些文件。
现在,如果您可以确定在使用特定的临时文件之后不再需要该文件,那么就不会删除该特定的文件。
在.NET中,您可以使用TempFileCollection
类来管理由应用程序清理的一组临时文件(请注意,它隐藏在CodeDom命名空间中)。 很明显,你不能删除任何你自己不拥有的文件,因为这些文件可能仍然被其他应用程序打开(删除它们可能会导致严重的问题)。
清理临时文件的责任应该在创建它们的应用程序上。 这很容易。 我使用类似下面的类:
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; } } }
如果您需要清理其他应用程序的临时文件,则需要一些与您的通信方式。 至少它应该能够提供一个信号量。 然而,这样做的复杂性要比原来的应用程序处理自己的文件更复杂。
我们有一个类似的文件生存期问题 – (winforms)应用程序可以从中央存储库中获取文档供用户查看,但用户应该能够关闭我们的应用程序,而不影响他们正在查看的文件。 由于安全问题,文档文件需要清理干净,所以不会太长时间。
我们使用的解决方案是在用户的隔离存储区中创建一个具有日期派生名称的文件夹,并将其用作当今的缓存。 在应用程序关闭和启动时,我们检查以前的日期缓存文件夹并删除它们(和内容)。
我相信当用户注销时它们将被删除。
早在人们每天关掉电脑的时候,这可能是一个完美的解决方案。
现在,人们可能会有几个月的时间没有注销,所以依靠它可能不是一个好主意。
另外,如果他们关闭机器而不关闭,那么文件也不会被删除。
您可以使用监视您写入的文件的文件系统监视器,并等待一段时间不活动(10分钟,1小时,1天或之后),然后删除文件。
这不会为一切工作。 有些程序可能有一个“打开”文件,但可能没有锁定底层文件。 如果发生这种情况,那么你将无法知道什么时候删除文件是安全的。
但是,我认为你可以忽略这个问题。 大多数人可能有硬盘空间过剩,所以他们可能不会遇到它。 如果他们这样做,我认为Windows弹出一个低磁盘空间对话框,让他们可以选择清除他们的临时目录,这将解决问题。
更新:
我认为Windows Update将每月重新启动一次用户的计算机,因此在发生这种情况时应该清除临时文件。
不能保证没有问题,但实际上我认为这应该是非常罕见的。
更新2:
由一个评论提示,我去了,实际测试这个,它看起来像Windows不会删除临时文件时,用户注销。 不过,我仍然说在OP的情况下,这不是一个真正的问题。 当它成为一个问题(因为磁盘空间不足),Windows将提示用户删除临时文件。
在ASP.NET中使用临时文件时,使用PAGE_DISPOSED事件删除您在页面中创建的任何临时文件。 否则,您可能会直到与DISPOSED之前不放手的组件争用。
我使用这个解决方案(相当可靠):
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)) { } } } } }
每次你需要临时文件使用:
var tempFile = TemporaryFiles.UseNew();
确保应用程序关闭或崩溃后,所有临时文件都被删除
TemporaryFiles.DeleteAllPreviouslyUsed();
在申请的开始。
你可以创建一个临时文件,在这个文件中你可以不断写入在这个过程中创建的文件名,在处理结束的时候可以(先决条件 – 实现IDisposable和)在操作完成后在Disponse方法中删除。
其他方式是每间隔执行一次清理的写入独立进程。
在文件末尾附加日期,并在当天结束时删除该日期,进程将在最后生成新的日期文件。
一个由divo tempfilecollection类给出的好建议。
希望能帮助到你。