如何创建在程序终止后自动删除的临时文件

问题描述:

我一直在寻找无处不在,我无法找到任何地方使用GetTempFileName创建的临时文件在任何地方都找不到这样的选项,一旦应用程序终止。如何创建在程序终止后自动删除的临时文件

我该怎么做?

+3

如果您打开该文件,则可以使用[FileOptions.DeleteOnClose](https://msdn.microsoft.com/en-us/library/system.io.fileoptions.aspx)。 – Blorgbeard

在创建文件使用FileOptions.DeleteOnClose

using (var fs = new FileStream(Path.GetTempFileName(), FileMode.Open, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose)) 
{ 
    // do your work here 
} 

一旦流被关闭的文件将被删除。

如果您需要文件打开整个时间,您可以用FileShare.ReadWrite | FileShare.Delete而不是FileShare.None打开流,然后在整个程序中需要访问该文件时再次打开相同的文件名。然后在退出程序时关闭流。

注意:您不一定需要显式关闭流,关闭程序的行为将关闭流并执行必要的清理以删除文件。如果您确实采用这种方法,请确保只要程序处于活动状态就可以参考活动的流,否则GC可能会清理流并在早期删除文件。

更新:如果你有电力损失,你仍然会在磁盘上有一个文件,但是如果你的程序被强制关闭了一个结束任务,文件仍然会被删除。删除操作在内核级而不是应用程序级上进行。一旦文件的最后一个句柄关闭,Windows本身就是删除文件的东西。

尽管您可能无法在断电时删除该文件,但还有另一个选项可以最大限度地减少留下的磁盘上的临时文件大小。这将要求您进一步深入并直接调用CreateFile。有一个标志FILE_ATTRIBUTE_TEMPORARY你可以使用,那么将做的是告诉windows不刷新写入磁盘,只要可能,就把它们保存在缓存中。有了这个属性,文件可能会被留下,但文件大小可能为0kB的可能性很大。

[DllImport("kernel32.dll", SetLastError = true, CharSet=CharSet.Unicode)] 
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, 
    uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, 
    uint dwFlagsAndAttributes, IntPtr hTemplateFile); 

public const uint OPEN_EXISTING = 3 
public const uint GENERIC_READ = 0x80000000; 
public const uint GENERIC_WRITE = 0x40000000; 
public const uint FILE_ATTRIBUTE_TEMPORARY = 0x100; 
public const uint FILE_FLAG_DELETE_ON_CLOSE = 0x04000000; 

public FileStream OpenTempFile() 
{ 
    var path = Path.GetTempFileName(); 
    var handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero 
          ,OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE 
          ,IntPtr.Zero); 
    if (handle.IsInvalid) 
    { 
     Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 
    } 
    return new FileStream(handle, FileAccess.ReadWrite); 
} 

上面的代码是在浏览器中编写的,因此可能包含一个或两个错误,但它会得到一个整体的想法。

UPDATE2:有一两件事可以做,以删除即使电源丢失的文件是使用WinAPI的通话MoveFileEx具有使用MOVEFILE_DELAY_UNTIL_REBOOT标志和传球IntPtr.ZerolpNewFileName删除在下次重新启动文件的选项。

+1

在系统异常关闭(即掉电)后,这能否可靠地清理文件? –

+1

@KirillShlenskiy看到我的更新。 –

+0

我喜欢用MOVEFILE_DELAY_UNTIL_REBOOT添加MoveFileEx。 –