Windows临时文件行为 - 是否被系统删除?

时间:2023-01-16 22:09:57

Using the .net framework you have the option to create temporary files with

使用.net框架,您可以选择使用.net框架创建临时文件

Path.GetTempFileName(); 

The MSDN doesn't tell us what happens to temporary files. I remember reading somewhere that they are deleted by the OS when it gets a restart. Is this true?

MSDN没有告诉我们临时文件会发生什么。我记得在某个地方读到它们在重启时会被操作系统删除。这是真的?

If the files aren't deleted by the OS, why are they called temporary? They are normal files in a normal directory.

如果操作系统没有删除这些文件,为什么它们被称为临时文件?它们是普通目录中的普通文件。

7 个解决方案

#1


41  

The short answer: they don't get deleted.

简短的回答:它们不会被删除。

The long answer: The managed Path.GetTempFileName() method calls the native Win32API GetTempFileName() method, like this:

答案很长:托管的Path.GetTempFileName()方法调用本机Win32API GetTempFileName()方法,如下所示:

//actual .NET 2.0 decompiled code 
// .NET Reflector rocks for looking at plumbing
public static string GetTempFileName()
{
    string tempPath = GetTempPath();
    new FileIOPermission(FileIOPermissionAccess.Write, tempPath).Demand();
    StringBuilder tmpFileName = new StringBuilder(260);
    if (Win32Native.GetTempFileName(tempPath, "tmp", 0, tmpFileName) == 0)
    {
        __Error.WinIOError();
    }
    return tmpFileName.ToString();
}

The documentation for the native method states:

本机方法的文档说明:

Windows临时文件行为 - 是否被系统删除? Temporary files whose names have been created by this function are not automatically deleted. To delete these files call DeleteFile.

名称由此函数创建的临时文件不会自动删除。要删除这些文件,请调用DeleteFile。

I have found a great article called "Those pesky temp files" (Archived Oct. 2007) that starts from basics and touches some less obvious problems of handling temporary files, like:

我找到了一篇很棒的文章,名为“那些讨厌的临时文件”(2007年10月存档),从基础知识开始,触及处理临时文件的一些不太明显的问题,如:

  • How to make sure the file is deleted (even if the app crashes! hint: FileOption.DeleteOnClose and let the kernel deal with it)
  • 如何确保文件被删除(即使应用程序崩溃!提示:FileOption.DeleteOnClose并让内核处理它)
  • How to get the correct caching policy for the file, to improve performance (hint: FileAttributes.Temporary)
  • 如何获取文件的正确缓存策略,以提高性能(提示:FileAttributes.Temporary)
  • How to make sure the contents of the file stay secure, because:
    • the file name is even more predictable with the managed method than with the unmanaged one
    • 使用托管方法比使用非托管方法更可预测文件名
    • the temp file is created, then closed, then you get the path to it (only to open it again), thus leaving a small window of opportunity for malicious code/users to hijack the file.
    • 创建临时文件,然后关闭,然后获取它的路径(仅重新打开它),从而为恶意代码/用户留下一个劫持文件的小机会窗口。
  • 如何确保文件的内容保持安全,因为:使用托管方法比使用非托管文件名创建临时文件更可预测文件名,然后关闭,然后获取文件路径(仅打开)它再次),从而为恶意代码/用户留下了一个劫持文件的小机会窗口。

C# Code from article:

来自文章的C#代码:

using System;
using System.IO;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security.AccessControl;

public static class PathUtility
{
    private const int defaultBufferSize = 0x1000; // 4KB

#region GetSecureDeleteOnCloseTempFileStream

    /// <summary>
    /// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream.
    /// </summary>
    /// <remarks>
    /// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
    /// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
    /// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
    /// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
    /// <para>The file sharing is set to none.</para>
    /// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
    /// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
    /// </remarks>
    /// <returns>The opened <see cref="FileStream"/> object.</returns>
    public static FileStream GetSecureDeleteOnCloseTempFileStream()
    {    
        return GetSecureDeleteOnCloseTempFileStream(defaultBufferSize, FileOptions.DeleteOnClose);    
    }

    /// <summary>
    /// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream with the specified buffer size.
    /// </summary>
    /// <remarks>
    /// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
    /// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
    /// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
    /// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
    /// <para>The file sharing is set to none.</para>
    /// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
    /// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
    /// </remarks>
    /// <param name="bufferSize">A positive <see cref="Int32"/> value greater than 0 indicating the buffer size.</param>
    /// <returns>The opened <see cref="FileStream"/> object.</returns>
    public static FileStream GetSecureDeleteOnCloseTempFileStream(int bufferSize)
    {
        return GetSecureDeleteOnCloseTempFileStream(bufferSize, FileOptions.DeleteOnClose);
    }

    /// <summary>
    /// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream with the specified buffer size and file options.
    /// </summary>  
    /// <remarks>
    /// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
    /// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
    /// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
    /// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
    /// <para>The file sharing is set to none.</para>
    /// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
    /// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
    /// <para>Use the <paramref name="options"/> parameter to specify additional file options. You can specify <see cref="FileOptions.Encrypted"/> to encrypt the file contents using the current user account. Specify <see cref="FileOptions.Asynchronous"/> to enable overlapped I/O when using asynchronous reads and writes.</para>
    /// </remarks>
    /// <param name="bufferSize">A positive <see cref="Int32"/> value greater than 0 indicating the buffer size.</param>
    /// <param name="options">A <see cref="FileOptions"/> value that specifies additional file options.</param>
    /// <returns>The opened <see cref="FileStream"/> object.</returns>
    public static FileStream GetSecureDeleteOnCloseTempFileStream(int bufferSize, FileOptions options)
    {    
        FileStream fs = GetSecureFileStream(Path.GetTempPath(), bufferSize, options | FileOptions.DeleteOnClose);

        File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.Temporary);

        return fs;    
    }

#endregion

#region GetSecureTempFileStream

    public static FileStream GetSecureTempFileStream()
    {    
        return GetSecureTempFileStream(defaultBufferSize, FileOptions.None);    
    }

    public static FileStream GetSecureTempFileStream(int bufferSize)
    {
        return GetSecureTempFileStream(bufferSize, FileOptions.None);
    }

    public static FileStream GetSecureTempFileStream(int bufferSize, FileOptions options)
    {
        FileStream fs = GetSecureFileStream(Path.GetTempPath(), bufferSize, options);

        File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.NotContentIndexed | FileAttributes.Temporary);

        return fs;
    }

    #endregion

#region GetSecureTempFileName

    public static string GetSecureTempFileName()
    {    
        return GetSecureTempFileName(false);    
    }

    public static string GetSecureTempFileName(bool encrypted)
    {    
        using (FileStream fs = GetSecureFileStream(Path.GetTempPath(), defaultBufferSize, encrypted ? FileOptions.Encrypted : FileOptions.None))
        {    
            File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.NotContentIndexed | FileAttributes.Temporary);

            return fs.Name;    
        }

    }

#endregion

#region GetSecureFileName

    public static string GetSecureFileName(string path)
    {    
        return GetSecureFileName(path, false);    
    }

    public static string GetSecureFileName(string path, bool encrypted)
    {    
        using (FileStream fs = GetSecureFileStream(path, defaultBufferSize, encrypted ? FileOptions.Encrypted : FileOptions.None))
        {    
            return fs.Name;    
        }    
    }

#endregion

#region GetSecureFileStream

    public static FileStream GetSecureFileStream(string path)
    {    
        return GetSecureFileStream(path, defaultBufferSize, FileOptions.None);    
    }

    public static FileStream GetSecureFileStream(string path, int bufferSize)
    {
        return GetSecureFileStream(path, bufferSize, FileOptions.None);
    }

    public static FileStream GetSecureFileStream(string path, int bufferSize, FileOptions options)
    {    
        if (path == null)
            throw new ArgumentNullException("path");

        if (bufferSize <= 0)
            throw new ArgumentOutOfRangeException("bufferSize");

        if ((options & ~(FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.Encrypted | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)) != FileOptions.None)
            throw new ArgumentOutOfRangeException("options");

        new FileIOPermission(FileIOPermissionAccess.Write, path).Demand();

        SecurityIdentifier user = WindowsIdentity.GetCurrent().User;

        FileSecurity fileSecurity = new FileSecurity();

        fileSecurity.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.FullControl, AccessControlType.Allow));

        fileSecurity.SetAccessRuleProtection(true, false);

        fileSecurity.SetOwner(user);

        // Attempt to create a unique file three times before giving up.
        // It is highly improbable that there will ever be a name *,
        // therefore we do not check to see if the file first exists.

        for (int attempt = 0; attempt < 3; attempt++)
        {    
            try
            {    
                return new FileStream(Path.Combine(path, Path.GetRandomFileName()),
                                        FileMode.CreateNew, FileSystemRights.FullControl,
                                        FileShare.None, bufferSize, options, fileSecurity);
            }

            catch (IOException)
            {
                if (attempt == 2)
                    throw;
            }

        }

        // This code can never be reached.
        // The compiler thinks otherwise.
        throw new IOException();

    }

#endregion

}

#2


8  

Based on the March files in my %tmp%, I'd say not.

根据我的%tmp%中的March文件,我会说不是。

Re why they are called temporary - because that is their expected usage. They aren't system files; they aren't application files, and they aren't user documents... they exist only to allow an app to do temporary processing (perhaps on large volumes of data), or often to pass data via IPC to another process. Hence they really are temporary.

为什么他们被称为临时 - 因为这是他们的预期用途。它们不是系统文件;它们不是应用程序文件,它们不是用户文档......它们只是为了允许应用程序进行临时处理(可能是大量数据),或者经常通过IPC将数据传递到另一个进程。因此他们真的是暂时的。

You should aim to delete any temp files you create, fatal "kill" etc not withstanding. I often use "using" for this - I create a wrapper class - i.e.

你应该瞄准删除你创建的任何临时文件,致命的“杀死”等不能承受。我经常使用“使用” - 我创建了一个包装类 - 即

sealed class TempFile : IDisposable { // formatted for space
    string path;
    public string Path {
        get {
            if(path==null) throw new ObjectDisposedException(GetType().Name);
            return path;
        }
    }
    public TempFile() : this(System.IO.Path.GetTempFileName()) { }

    public TempFile(string path) {
        if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
        this.path = path;
    }

    private void Dispose(bool disposing) {
        if (path != null) {
            try {
                File.Delete(path);
            } catch { } // best endeavours...
            path = null;
        }
    }
    public void Dispose() {
        GC.SuppressFinalize(this);
        Dispose(true);
    }
    ~TempFile() {
        Dispose(false);
    }
}

#3


5  

There is a FileOptions.DeleteOnClose option which might do what you want.

有一个FileOptions.DeleteOnClose选项可以做你想要的。

Here is a link to the MSDN page.

这是MSDN页面的链接。

#4


1  

No, this is not true. Basically, your app is responsible for cleaning up its own mess. If you don't, temporary files will accumulate over time.

不,这不是真的。基本上,您的应用程序负责清理自己的混乱。如果不这样做,临时文件将随着时间的推移而累积。

#5


0  

No, it lies in the responsibility of the software (read: the developer) that creates a temporary file to dispose of it.

不,这取决于软件(读取:开发人员)的责任,该软件会创建一个临时文件来处理它。

Have a look in your own temp folder to see how well that works ;-)

看看你自己的临时文件夹,看看它有多好用;-)

#6


0  

They are called temporary because in most cases, the user can assume she can safely clean up the mess in the temp dirs... If not, in general, these files are locked anyway.

它们被称为临时的,因为在大多数情况下,用户可以假设她可以安全地清理临时目录中的混乱......如果不是,通常情况下,这些文件无论如何都会被锁定。

In general, these files should be short lived: create them, use them for whatever need you have, delete them on the spot. At worse, delete them when exiting the application.

一般来说,这些文件应该是短暂的:创建它们,将它们用于任何你需要的东西,当场删除它们。更糟糕的是,在退出应用程序时删除它们。

Sometime, you cannot, eg. an archive manager or a VCS allowing to look at a file with an editor (or diff viewer, etc.), but closed before the editor (or not able to monitor the spawned process...).

有时,你不能,例如。存档管理器或VCS允许使用编辑器(或差异查看器等)查看文件,但在编辑器之前关闭(或者无法监视生成的进程...)。

#7


-2  

I've read on the internet a lot of times that people don't want to use Path.GetTempFileName because they say it could return an already existing file, to solve the problem you can make a filename based on a GUID.

我已经在互联网上阅读了很多次,人们不想使用Path.GetTempFileName,因为他们说它可以返回一个已经存在的文件,以解决你可以根据GUID创建文件名的问题。

This Function solves that Problem: Iterates until it finds a nonexistent file name with an specific extension.

此函数解决了该问题:迭代直到找到具有特定扩展名的不存在的文件名。

VB.net

VB.net

Public Shared Function GetTempFileName(ByVal extensionWithDot As String) As String
    Dim tempFileName As String
    Do
        tempFileName = System.IO.Path.GetTempFileName
        If extensionWithDot IsNot Nothing Then
            tempFileName = tempFileName.Replace(System.IO.Path.GetExtension(tempFileName), extensionWithDot)
        End If
    Loop While System.IO.File.Exists(tempFileName)
    Return tempFileName
End Function

C#:

C#:

public static string GetTempFileName(string extensionWithDot)
{
    string tempFileName = null;
    do {
        tempFileName = System.IO.Path.GetTempFileName;
        if (extensionWithDot != null) {
            tempFileName = tempFileName.Replace(System.IO.Path.GetExtension(tempFileName), extensionWithDot);
        }
    } while (System.IO.File.Exists(tempFileName));
    return tempFileName;
}

Note: I use argument extensionWithDot because System.IO.Path.GetExtension returns with dot.

注意:我使用参数extensionWithDot,因为System.IO.Path.GetExtension返回点。

#1


41  

The short answer: they don't get deleted.

简短的回答:它们不会被删除。

The long answer: The managed Path.GetTempFileName() method calls the native Win32API GetTempFileName() method, like this:

答案很长:托管的Path.GetTempFileName()方法调用本机Win32API GetTempFileName()方法,如下所示:

//actual .NET 2.0 decompiled code 
// .NET Reflector rocks for looking at plumbing
public static string GetTempFileName()
{
    string tempPath = GetTempPath();
    new FileIOPermission(FileIOPermissionAccess.Write, tempPath).Demand();
    StringBuilder tmpFileName = new StringBuilder(260);
    if (Win32Native.GetTempFileName(tempPath, "tmp", 0, tmpFileName) == 0)
    {
        __Error.WinIOError();
    }
    return tmpFileName.ToString();
}

The documentation for the native method states:

本机方法的文档说明:

Windows临时文件行为 - 是否被系统删除? Temporary files whose names have been created by this function are not automatically deleted. To delete these files call DeleteFile.

名称由此函数创建的临时文件不会自动删除。要删除这些文件,请调用DeleteFile。

I have found a great article called "Those pesky temp files" (Archived Oct. 2007) that starts from basics and touches some less obvious problems of handling temporary files, like:

我找到了一篇很棒的文章,名为“那些讨厌的临时文件”(2007年10月存档),从基础知识开始,触及处理临时文件的一些不太明显的问题,如:

  • How to make sure the file is deleted (even if the app crashes! hint: FileOption.DeleteOnClose and let the kernel deal with it)
  • 如何确保文件被删除(即使应用程序崩溃!提示:FileOption.DeleteOnClose并让内核处理它)
  • How to get the correct caching policy for the file, to improve performance (hint: FileAttributes.Temporary)
  • 如何获取文件的正确缓存策略,以提高性能(提示:FileAttributes.Temporary)
  • How to make sure the contents of the file stay secure, because:
    • the file name is even more predictable with the managed method than with the unmanaged one
    • 使用托管方法比使用非托管方法更可预测文件名
    • the temp file is created, then closed, then you get the path to it (only to open it again), thus leaving a small window of opportunity for malicious code/users to hijack the file.
    • 创建临时文件,然后关闭,然后获取它的路径(仅重新打开它),从而为恶意代码/用户留下一个劫持文件的小机会窗口。
  • 如何确保文件的内容保持安全,因为:使用托管方法比使用非托管文件名创建临时文件更可预测文件名,然后关闭,然后获取文件路径(仅打开)它再次),从而为恶意代码/用户留下了一个劫持文件的小机会窗口。

C# Code from article:

来自文章的C#代码:

using System;
using System.IO;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security.AccessControl;

public static class PathUtility
{
    private const int defaultBufferSize = 0x1000; // 4KB

#region GetSecureDeleteOnCloseTempFileStream

    /// <summary>
    /// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream.
    /// </summary>
    /// <remarks>
    /// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
    /// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
    /// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
    /// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
    /// <para>The file sharing is set to none.</para>
    /// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
    /// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
    /// </remarks>
    /// <returns>The opened <see cref="FileStream"/> object.</returns>
    public static FileStream GetSecureDeleteOnCloseTempFileStream()
    {    
        return GetSecureDeleteOnCloseTempFileStream(defaultBufferSize, FileOptions.DeleteOnClose);    
    }

    /// <summary>
    /// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream with the specified buffer size.
    /// </summary>
    /// <remarks>
    /// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
    /// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
    /// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
    /// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
    /// <para>The file sharing is set to none.</para>
    /// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
    /// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
    /// </remarks>
    /// <param name="bufferSize">A positive <see cref="Int32"/> value greater than 0 indicating the buffer size.</param>
    /// <returns>The opened <see cref="FileStream"/> object.</returns>
    public static FileStream GetSecureDeleteOnCloseTempFileStream(int bufferSize)
    {
        return GetSecureDeleteOnCloseTempFileStream(bufferSize, FileOptions.DeleteOnClose);
    }

    /// <summary>
    /// Creates a unique, randomly named, secure, zero-byte temporary file on disk, which is automatically deleted when it is no longer in use. Returns the opened file stream with the specified buffer size and file options.
    /// </summary>  
    /// <remarks>
    /// <para>The generated file name is a cryptographically strong, random string. The file name is guaranteed to be unique to the system's temporary folder.</para>
    /// <para>The <see cref="GetSecureDeleteOnCloseTempFileStream"/> method will raise an <see cref="IOException"/> if no unique temporary file name is available. Although this is possible, it is highly improbable. To resolve this error, delete all uneeded temporary files.</para>
    /// <para>The file is created as a zero-byte file in the system's temporary folder.</para>
    /// <para>The file owner is set to the current user. The file security permissions grant full control to the current user only.</para>
    /// <para>The file sharing is set to none.</para>
    /// <para>The file is marked as a temporary file. File systems avoid writing data back to mass storage if sufficient cache memory is available, because an application deletes a temporary file after a handle is closed. In that case, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.</para>
    /// <para>The system deletes the file immediately after it is closed or the <see cref="FileStream"/> is finalized.</para>
    /// <para>Use the <paramref name="options"/> parameter to specify additional file options. You can specify <see cref="FileOptions.Encrypted"/> to encrypt the file contents using the current user account. Specify <see cref="FileOptions.Asynchronous"/> to enable overlapped I/O when using asynchronous reads and writes.</para>
    /// </remarks>
    /// <param name="bufferSize">A positive <see cref="Int32"/> value greater than 0 indicating the buffer size.</param>
    /// <param name="options">A <see cref="FileOptions"/> value that specifies additional file options.</param>
    /// <returns>The opened <see cref="FileStream"/> object.</returns>
    public static FileStream GetSecureDeleteOnCloseTempFileStream(int bufferSize, FileOptions options)
    {    
        FileStream fs = GetSecureFileStream(Path.GetTempPath(), bufferSize, options | FileOptions.DeleteOnClose);

        File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.Temporary);

        return fs;    
    }

#endregion

#region GetSecureTempFileStream

    public static FileStream GetSecureTempFileStream()
    {    
        return GetSecureTempFileStream(defaultBufferSize, FileOptions.None);    
    }

    public static FileStream GetSecureTempFileStream(int bufferSize)
    {
        return GetSecureTempFileStream(bufferSize, FileOptions.None);
    }

    public static FileStream GetSecureTempFileStream(int bufferSize, FileOptions options)
    {
        FileStream fs = GetSecureFileStream(Path.GetTempPath(), bufferSize, options);

        File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.NotContentIndexed | FileAttributes.Temporary);

        return fs;
    }

    #endregion

#region GetSecureTempFileName

    public static string GetSecureTempFileName()
    {    
        return GetSecureTempFileName(false);    
    }

    public static string GetSecureTempFileName(bool encrypted)
    {    
        using (FileStream fs = GetSecureFileStream(Path.GetTempPath(), defaultBufferSize, encrypted ? FileOptions.Encrypted : FileOptions.None))
        {    
            File.SetAttributes(fs.Name, File.GetAttributes(fs.Name) | FileAttributes.NotContentIndexed | FileAttributes.Temporary);

            return fs.Name;    
        }

    }

#endregion

#region GetSecureFileName

    public static string GetSecureFileName(string path)
    {    
        return GetSecureFileName(path, false);    
    }

    public static string GetSecureFileName(string path, bool encrypted)
    {    
        using (FileStream fs = GetSecureFileStream(path, defaultBufferSize, encrypted ? FileOptions.Encrypted : FileOptions.None))
        {    
            return fs.Name;    
        }    
    }

#endregion

#region GetSecureFileStream

    public static FileStream GetSecureFileStream(string path)
    {    
        return GetSecureFileStream(path, defaultBufferSize, FileOptions.None);    
    }

    public static FileStream GetSecureFileStream(string path, int bufferSize)
    {
        return GetSecureFileStream(path, bufferSize, FileOptions.None);
    }

    public static FileStream GetSecureFileStream(string path, int bufferSize, FileOptions options)
    {    
        if (path == null)
            throw new ArgumentNullException("path");

        if (bufferSize <= 0)
            throw new ArgumentOutOfRangeException("bufferSize");

        if ((options & ~(FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.Encrypted | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)) != FileOptions.None)
            throw new ArgumentOutOfRangeException("options");

        new FileIOPermission(FileIOPermissionAccess.Write, path).Demand();

        SecurityIdentifier user = WindowsIdentity.GetCurrent().User;

        FileSecurity fileSecurity = new FileSecurity();

        fileSecurity.AddAccessRule(new FileSystemAccessRule(user, FileSystemRights.FullControl, AccessControlType.Allow));

        fileSecurity.SetAccessRuleProtection(true, false);

        fileSecurity.SetOwner(user);

        // Attempt to create a unique file three times before giving up.
        // It is highly improbable that there will ever be a name *,
        // therefore we do not check to see if the file first exists.

        for (int attempt = 0; attempt < 3; attempt++)
        {    
            try
            {    
                return new FileStream(Path.Combine(path, Path.GetRandomFileName()),
                                        FileMode.CreateNew, FileSystemRights.FullControl,
                                        FileShare.None, bufferSize, options, fileSecurity);
            }

            catch (IOException)
            {
                if (attempt == 2)
                    throw;
            }

        }

        // This code can never be reached.
        // The compiler thinks otherwise.
        throw new IOException();

    }

#endregion

}

#2


8  

Based on the March files in my %tmp%, I'd say not.

根据我的%tmp%中的March文件,我会说不是。

Re why they are called temporary - because that is their expected usage. They aren't system files; they aren't application files, and they aren't user documents... they exist only to allow an app to do temporary processing (perhaps on large volumes of data), or often to pass data via IPC to another process. Hence they really are temporary.

为什么他们被称为临时 - 因为这是他们的预期用途。它们不是系统文件;它们不是应用程序文件,它们不是用户文档......它们只是为了允许应用程序进行临时处理(可能是大量数据),或者经常通过IPC将数据传递到另一个进程。因此他们真的是暂时的。

You should aim to delete any temp files you create, fatal "kill" etc not withstanding. I often use "using" for this - I create a wrapper class - i.e.

你应该瞄准删除你创建的任何临时文件,致命的“杀死”等不能承受。我经常使用“使用” - 我创建了一个包装类 - 即

sealed class TempFile : IDisposable { // formatted for space
    string path;
    public string Path {
        get {
            if(path==null) throw new ObjectDisposedException(GetType().Name);
            return path;
        }
    }
    public TempFile() : this(System.IO.Path.GetTempFileName()) { }

    public TempFile(string path) {
        if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
        this.path = path;
    }

    private void Dispose(bool disposing) {
        if (path != null) {
            try {
                File.Delete(path);
            } catch { } // best endeavours...
            path = null;
        }
    }
    public void Dispose() {
        GC.SuppressFinalize(this);
        Dispose(true);
    }
    ~TempFile() {
        Dispose(false);
    }
}

#3


5  

There is a FileOptions.DeleteOnClose option which might do what you want.

有一个FileOptions.DeleteOnClose选项可以做你想要的。

Here is a link to the MSDN page.

这是MSDN页面的链接。

#4


1  

No, this is not true. Basically, your app is responsible for cleaning up its own mess. If you don't, temporary files will accumulate over time.

不,这不是真的。基本上,您的应用程序负责清理自己的混乱。如果不这样做,临时文件将随着时间的推移而累积。

#5


0  

No, it lies in the responsibility of the software (read: the developer) that creates a temporary file to dispose of it.

不,这取决于软件(读取:开发人员)的责任,该软件会创建一个临时文件来处理它。

Have a look in your own temp folder to see how well that works ;-)

看看你自己的临时文件夹,看看它有多好用;-)

#6


0  

They are called temporary because in most cases, the user can assume she can safely clean up the mess in the temp dirs... If not, in general, these files are locked anyway.

它们被称为临时的,因为在大多数情况下,用户可以假设她可以安全地清理临时目录中的混乱......如果不是,通常情况下,这些文件无论如何都会被锁定。

In general, these files should be short lived: create them, use them for whatever need you have, delete them on the spot. At worse, delete them when exiting the application.

一般来说,这些文件应该是短暂的:创建它们,将它们用于任何你需要的东西,当场删除它们。更糟糕的是,在退出应用程序时删除它们。

Sometime, you cannot, eg. an archive manager or a VCS allowing to look at a file with an editor (or diff viewer, etc.), but closed before the editor (or not able to monitor the spawned process...).

有时,你不能,例如。存档管理器或VCS允许使用编辑器(或差异查看器等)查看文件,但在编辑器之前关闭(或者无法监视生成的进程...)。

#7


-2  

I've read on the internet a lot of times that people don't want to use Path.GetTempFileName because they say it could return an already existing file, to solve the problem you can make a filename based on a GUID.

我已经在互联网上阅读了很多次,人们不想使用Path.GetTempFileName,因为他们说它可以返回一个已经存在的文件,以解决你可以根据GUID创建文件名的问题。

This Function solves that Problem: Iterates until it finds a nonexistent file name with an specific extension.

此函数解决了该问题:迭代直到找到具有特定扩展名的不存在的文件名。

VB.net

VB.net

Public Shared Function GetTempFileName(ByVal extensionWithDot As String) As String
    Dim tempFileName As String
    Do
        tempFileName = System.IO.Path.GetTempFileName
        If extensionWithDot IsNot Nothing Then
            tempFileName = tempFileName.Replace(System.IO.Path.GetExtension(tempFileName), extensionWithDot)
        End If
    Loop While System.IO.File.Exists(tempFileName)
    Return tempFileName
End Function

C#:

C#:

public static string GetTempFileName(string extensionWithDot)
{
    string tempFileName = null;
    do {
        tempFileName = System.IO.Path.GetTempFileName;
        if (extensionWithDot != null) {
            tempFileName = tempFileName.Replace(System.IO.Path.GetExtension(tempFileName), extensionWithDot);
        }
    } while (System.IO.File.Exists(tempFileName));
    return tempFileName;
}

Note: I use argument extensionWithDot because System.IO.Path.GetExtension returns with dot.

注意:我使用参数extensionWithDot,因为System.IO.Path.GetExtension返回点。