temporales limpieza internet eliminar como borrar archivos .net io

.net - limpieza - eliminar archivos temporales windows 7



Creando carpetas temporales (13)

Algo como...

using System.IO; string path = Path.GetTempPath() + Path.GetRandomFileName(); while (Directory.Exists(path)) path = Path.GetTempPath() + Path.GetRandomFileName(); Directory.CreateDirectory(path);

Estoy trabajando en un programa que necesita crear varias carpetas temporales para la aplicación. Estos no serán vistos por el usuario. La aplicación está escrita en VB.net. Puedo pensar en algunas maneras de hacerlo, como el nombre de la carpeta incremental o los nombres de las carpetas con números al azar, pero me preguntaba cómo otras personas resuelven este problema.


La ventaja de utilizar System.IO.Path.GetTempFileName es que será un archivo en la ruta local del usuario (es decir, no itinerante). Aquí es exactamente donde lo desea para permisos y razones de seguridad.


Las respuestas combinadas de @ adam-wright y pix0r funcionarán mejor en mi humilde opinión:

using System.IO; string path = Path.GetTempPath() + Path.GetRandomFileName(); while (Directory.Exists(path)) path = Path.GetTempPath() + Path.GetRandomFileName(); File.Delete(path); Directory.CreateDirectory(path);


Puede generar un GUID para sus nombres de carpetas temporales.



Siempre que el nombre de la carpeta no tenga que ser significativo, ¿qué hay de usar un GUID para ellos?


Tienes que usar System.IO.Path.GetTempFileName()

Crea un archivo temporal de cero bytes con nombre exclusivo en el disco y devuelve la ruta completa de ese archivo.

Puede usar System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName()) para obtener solo la información de la carpeta temporal y crear sus carpetas allí

Se crean en la carpeta temp de Windows y eso se considera una buena práctica


Solo para aclarar:

System.IO.Path.GetTempPath()

devuelve solo la ruta de la carpeta a la carpeta temporal.

System.IO.Path.GetTempFileName()

devuelve el nombre completo del archivo (incluida la ruta) así que esto:

System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetTempFileName())

es redundante


Hay una posible condición de carrera cuando:

  • crear un archivo temporal con GetTempFileName() , eliminarlo y crear una carpeta con el mismo nombre, o
  • usando GetRandomFileName() o Guid.NewGuid.ToString para nombrar una carpeta y crear la carpeta más tarde

Con GetTempFileName() después de que se produce la eliminación, otra aplicación podría crear correctamente un archivo temporal con el mismo nombre. The CreateDirectory() fallaría.

Del mismo modo, entre llamar a GetRandomFileName() y crear el directorio, otro proceso podría crear un archivo o directorio con el mismo nombre, lo que también CreateDirectory() resultado la CreateDirectory() de CreateDirectory() .

Para la mayoría de las aplicaciones, está bien que un directorio temporal falle debido a una condición de carrera. Es extremadamente raro después de todo. Para ellos, estas carreras a menudo pueden ser ignoradas.

En el mundo de scripts de shell de Unix, crear directorios y archivos temporales de una manera segura y sin carreras es un gran problema. Muchas máquinas tienen usuarios múltiples (hostiles), piense en un host web compartido, y muchos scripts y aplicaciones necesitan crear de forma segura archivos temporales y directorios en el directorio compartido / tmp. Consulte Creación segura de archivos temporales en scripts de shell para una discusión sobre cómo crear directorios temporales de forma segura desde scripts de shell.


Actualización: archivo agregado. Incluye verificación por comentario (2012-jun-19)

Esto es lo que he usado en VB.NET. Esencialmente el mismo que se presentó, excepto que generalmente no quería crear la carpeta de inmediato.

La ventaja de utilizar GetRandomFilename es que no crea un archivo, por lo que no tiene que limpiar si usa el nombre para algo que no sea un archivo. Me gusta usarlo para el nombre de la carpeta.

Private Function GetTempFolder() As String Dim folder As String = Path.Combine(Path.GetTempPath, Path.GetRandomFileName) Do While Directory.Exists(folder) or File.Exists(folder) folder = Path.Combine(Path.GetTempPath, Path.GetRandomFileName) Loop Return folder End Function

Ejemplo de nombre de archivo aleatorio :

C: / Documents and Settings / username / Configuración local / Temp / u3z5e0co.tvq

Aquí hay una variación usando un Guid para obtener el nombre de la carpeta temporal.

Private Function GetTempFolderGuid() As String Dim folder As String = Path.Combine(Path.GetTempPath, Guid.NewGuid.ToString) Do While Directory.Exists(folder) or File.Exists(folder) folder = Path.Combine(Path.GetTempPath, Guid.NewGuid.ToString) Loop Return folder End Function

Ejemplo de guid :

C: / Documents and Settings / username / Configuración local / Temp / 2dbc6db7-2d45-4b75-b27f-0bd492c60496


Dim NewFolder = System.IO.Directory.CreateDirectory(IO.Path.Combine(IO.Path.GetTempPath, Guid.NewGuid.ToString))


@JonathanWright sugiere que CreateDirectory fallará cuando ya haya una carpeta. Si leo Directory.CreateDirectory, dice ''Este objeto se devuelve independientemente de si ya existe un directorio en la ruta especificada''. Lo que significa que no se detecta una carpeta creada entre verificar y crear.

Me gusta el CreateDirectoryTransacted () sugerido por @DanielTrebbien pero esta función está en desuso.

La única solución que veo que queda es usar la c api y llamar a '' CreateDirectory '' allí como lo hace el error si la carpeta existe si realmente necesita asegurarse de cubrir toda la condición de carrera. Eso daría como resultado algo como esto:

Private Function GetTempFolder() As String Dim folder As String Dim succes as Boolean = false Do While not succes folder = Path.Combine(Path.GetTempPath, Path.GetRandomFileName) success = c_api_create_directory(folder) Loop Return folder End Function


Como @JonathanWright señaló , existen condiciones de carrera para las soluciones:

  • Cree un archivo temporal con GetTempFileName() , elimínelo y cree una carpeta con el mismo nombre
  • Use GetRandomFileName() o Guid.NewGuid.ToString para crear un nombre de carpeta aleatorio, compruebe si existe y Guid.NewGuid.ToString si no.

Sin embargo, es posible crear un directorio temporal único atómicamente utilizando la API Transactional NTFS (TxF).

TxF tiene una función CreateDirectoryTransacted() que se puede invocar a través de Invoke de plataforma. Para hacer esto, adapté el código de Mohammad Elsheimy para llamar a CreateFileTransacted() :

// using System.ComponentModel; // using System.Runtime.InteropServices; // using System.Transactions; [ComImport] [Guid("79427a2b-f895-40e0-be79-b57dc82ed231")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IKernelTransaction { void GetHandle(out IntPtr pHandle); } // 2.2 Win32 Error Codes <http://msdn.microsoft.com/en-us/library/cc231199.aspx> public const int ERROR_PATH_NOT_FOUND = 0x3; public const int ERROR_ALREADY_EXISTS = 0xb7; public const int ERROR_EFS_NOT_ALLOWED_IN_TRANSACTION = 0x1aaf; [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern bool CreateDirectoryTransacted(string lpTemplateDirectory, string lpNewDirectory, IntPtr lpSecurityAttributes, IntPtr hTransaction); /// <summary> /// Creates a uniquely-named directory in the directory named by <paramref name="tempPath"/> and returns the path to it. /// </summary> /// <param name="tempPath">Path of a directory in which the temporary directory will be created.</param> /// <returns>The path of the newly-created temporary directory within <paramref name="tempPath"/>.</returns> public static string GetTempDirectoryName(string tempPath) { string retPath; using (TransactionScope transactionScope = new TransactionScope()) { IKernelTransaction kernelTransaction = (IKernelTransaction)TransactionInterop.GetDtcTransaction(Transaction.Current); IntPtr hTransaction; kernelTransaction.GetHandle(out hTransaction); while (!CreateDirectoryTransacted(null, retPath = Path.Combine(tempPath, Path.GetRandomFileName()), IntPtr.Zero, hTransaction)) { int lastWin32Error = Marshal.GetLastWin32Error(); switch (lastWin32Error) { case ERROR_ALREADY_EXISTS: break; default: throw new Win32Exception(lastWin32Error); } } transactionScope.Complete(); } return retPath; } /// <summary> /// Equivalent to <c>GetTempDirectoryName(Path.GetTempPath())</c>. /// </summary> /// <seealso cref="GetTempDirectoryName(string)"/> public static string GetTempDirectoryName() { return GetTempDirectoryName(Path.GetTempPath()); }