Подтвердить что ты не робот

Временные файлы Windows - удалены ли они системой?

Используя инфраструктуру .net, вы можете создавать временные файлы с помощью

Path.GetTempFileName(); 

MSDN не сообщает нам, что происходит с временными файлами. Я помню, где-то читал, что они удаляются ОС при перезапуске. Это правда?

Если файлы не удаляются ОС, почему они называются временными? Это обычные файлы в обычном каталоге.

4b9b3361

Ответ 1

Короткий ответ: они не удаляются.

Длинный ответ: Управляемый метод 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();
}

В документации для собственного метода указано:

Временные файлы, имена которых были созданы этой функцией, не удаляются автоматически. Чтобы удалить эти файлы, вызовите DeleteFile.

Я нашел замечательную статью под названием "Эти надменные файлы temp" (Archived Oct. 2007), которая начинается с основ и затрагивает некоторые менее очевидные проблемы обработки временных файлов, например:

  • Как убедиться, что файл удален (даже если приложение сработает! hint: FileOption.DeleteOnClose и пусть ядро ​​справится с ним )
  • Как получить правильную политику кэширования для файла, чтобы повысить производительность (подсказка: FileAttributes.Temporary)
  • Как убедиться, что содержимое файла остается в безопасности, потому что:
    • имя файла еще более предсказуемо с помощью управляемого метода, чем с неуправляемым
    • файл temp создается, затем закрывается, затем вы получаете путь к нему (только для его открытия), оставляя при этом небольшое окно возможностей для вредоносного кода/пользователей для захвата файла.

С# Код из статьи:

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 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 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 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 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 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 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 clash,
        // 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

Основываясь на файлах March в моем% tmp%, я бы сказал, что нет.

Re, почему они называются временными, потому что это их ожидаемое использование. Они не являются системными файлами; они не являются файлами приложений, и они не являются документами пользователя... они существуют только для того, чтобы приложение могло выполнять временную обработку (возможно, на больших объемах данных) или часто передавать данные через IPC в другой процесс. Следовательно, они действительно временны.

Вы должны стремиться к удалению любых создаваемых вами файлов temp, фатальных "kill" и т.д., которые не выдерживают. Я часто использую "использование" для этого - создаю класс-оболочку - т.е.

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

Существует опция FileOptions.DeleteOnClose, которая может делать то, что вы хотите.

Вот ссылка на страницу MSDN.

Ответ 4

Нет, это неправда. В основном, ваше приложение отвечает за очистку своего беспорядка. Если вы этого не сделаете, временные файлы будут накапливаться с течением времени.

Ответ 5

Нет, он лежит в основе программного обеспечения (читайте: разработчик), который создает временный файл, чтобы избавиться от него.

Посмотрите в своей собственной временной папке, чтобы увидеть, насколько хорошо это работает; -)

Ответ 6

Они называются временными, потому что в большинстве случаев пользователь может предположить, что она может безопасно очистить беспорядок во временном каталоге... Если нет, в общем, эти файлы все равно заблокированы.

В общем, эти файлы должны быть недолговечными: создавайте их, используйте их для любой необходимости, удаляя их на месте. В худшем случае удалите их при выходе из приложения.

Иногда вы не можете, например. диспетчер архива или VCS, позволяющий просматривать файл с помощью редактора (или средства просмотра различий и т.д.), но закрывать перед редактором (или не в состоянии контролировать порожденный процесс...).

Ответ 7

Я читал в Интернете много раз, что люди не хотят использовать Path.GetTempFileName, потому что говорят, что он может вернуть уже существующий файл, чтобы решить проблему, вы можете сделать имя файла на основе GUID.

Эта функция решает эту проблему: Итерирует, пока не найдет несуществующее имя файла с определенным расширением.

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

С#:

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

Примечание. Я использую аргумент extensionWithDot, потому что System.IO.Path.GetExtension возвращает с точкой.