Je travaille sur un programme qui doit créer plusieurs dossiers temporaires pour l'application. Ceux-ci ne seront pas vus par l'utilisateur. L'application est écrite sur VB.net. Je peux penser à quelques façons de le faire comme le nom de dossier incrémental ou des noms de dossiers numérotés au hasard, mais je me demandais, comment les autres personnes à résoudre ce problème?Création de dossiers temporaires
Répondre
Mise à jour: Ajouté File.Exists vérifier par commentaire (2012-juin-19)
Voici ce que je l'ai utilisé dans VB.NET. Essentiellement le même que présenté, sauf que je ne voulais généralement pas créer le dossier immédiatement.
L'avantage d'utiliser GetRandomFilename est qu'il ne crée pas de fichier, donc vous n'avez pas besoin de nettoyer si vous utilisez le nom pour autre chose qu'un fichier. Comme l'utiliser pour le nom du dossier.
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
aléatoire Nom du fichier Exemple:
C: \ Documents and Settings \ nom d'utilisateur \ Local Settings \ Temp \ u3z5e0co.tvq
Voici une variante utilisant un Guid pour obtenir la nom du dossier temporaire.
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
guid Exemple:
C: \ Documents and Settings \ nom d'utilisateur \ Local Settings \ Temp \ 2dbc6db7-2d45-4b75-B27F-0bd492c60496
Tant que le nom du dossier n'a pas besoin d'être significatif, que diriez-vous d'utiliser un GUID pour eux?
Vous pouvez générer un GUID pour vos noms de dossiers temporaires.
Vous pouvez utiliser GetTempFileName pour créer un fichier temporaire , puis supprimer et recréer ce fichier en tant que répertoire.
Note: lien n'a pas fonctionné, copier/coller à partir de: http://msdn.microsoft.com/en-us/library/aa364991(VS.85).aspx
Vous devez utiliser System.IO.Path.GetTempFileName()
crée un fichier temporaire au nom unique, zéro octet sur le disque et retourne le chemin complet de ce fichier.
Vous pouvez utiliser System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName())
pour obtenir uniquement les informations du dossier temp, et créer vos dossiers là-bas
Ils sont créés dans le dossier Windows temp et considérons une meilleure pratique
Do ** NOT ** do this. L'appel de 'System.IO.Path.GetDirectoryName' sur' System.IO.Path.GetTempFileName' est le pire remplacement de 'System.IO.Path.GetTempPath', car il crée un fichier qui reste derrière. – Jaykul
Quelque chose comme .. .
using System.IO;
string path = Path.GetTempPath() + Path.GetRandomFileName();
while (Directory.Exists(path))
path = Path.GetTempPath() + Path.GetRandomFileName();
Directory.CreateDirectory(path);
peut-être avec un try-catch pour ré-entrer la boucle si vous ne parvenez pas à créer le répertoire ;-) – Jaykul
réponses combinées de @ adam-wright et pix0r fonctionnera le mieux à mon humble avis:
using System.IO;
string path = Path.GetTempPath() + Path.GetRandomFileName();
while (Directory.Exists(path))
path = Path.GetTempPath() + Path.GetRandomFileName();
File.Delete(path);
Directory.CreateDirectory(path);
L'avantage d'utiliser System.IO.Path.GetTempFileName est qu'il s'agira d'un fichier dans le chemin local de l'utilisateur (c'est-à-dire, non itinérant). C'est exactement où vous le voudriez pour des raisons de permissions et de sécurité.
Juste pour clarifier:
System.IO.Path.GetTempPath()
renvoie simplement le chemin d'accès au dossier temporaire.
System.IO.Path.GetTempFileName()
retourne le nom de fichier complet (y compris le chemin) donc ce:
System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetTempFileName())
est redondant.
GetTempPath et GetTempFileName sont 2 méthodes complètement différentes. GetTempPath renvoie uniquement l'emplacement du dossier temporaire du système, tandis que GetTempFileName crée un fichier temporaire de longueur nulle et renvoie le chemin complet de ce fichier. –
Il y a une condition de course possible lorsque:
- la création d'un fichier temporaire avec
GetTempFileName()
, supprimer et faire un dossier avec le même nom, ou - utilisant
GetRandomFileName()
ouGuid.NewGuid.ToString
pour nommer un dossier et la création le dossier plus tard
Avec GetTempFileName()
après la suppression se produit, une autre application peut créer avec succès un fichier temporaire avec le même nom. Le CreateDirectory()
échouerait alors.
De même, entre l'appel GetRandomFileName()
et la création du répertoire, un autre processus peut créer un fichier ou un répertoire portant le même nom, ce qui entraîne à nouveau l'échec de CreateDirectory()
.
Pour la plupart des applications, il est possible qu'un répertoire temporaire échoue en raison d'une condition de concurrence. C'est extrêmement rare après tout. Pour eux, ces courses peuvent souvent être ignorées.
Dans le monde des scripts shell Unix, la création de fichiers et de répertoires temporaires dans un environnement sécurisé et sécurisé est un gros problème. De nombreuses machines ont plusieurs utilisateurs (hostiles) - pensez à un hébergeur partagé - et de nombreux scripts et applications doivent créer en toute sécurité des fichiers temporaires et des répertoires dans le répertoire partagé/tmp. Voir Safely Creating Temporary Files in Shell Scripts pour une discussion sur la façon de créer en toute sécurité des répertoires temporaires à partir de scripts shell.
Comme @JonathanWright pointed out, les conditions de course existent pour les solutions:
- Créer un fichier temporaire avec
GetTempFileName()
, supprimez-le et créez un dossier avec le même nom - Utilisez
GetRandomFileName()
ouGuid.NewGuid.ToString
pour créer un nom de dossier aléatoire, vérifiez s'il existe et créez-le sinon.
Il est toutefois possible de créer un répertoire temporaire unique de manière atomique en utilisant l'API Transactional NTFS (TxF).
TxF dispose d'une fonction CreateDirectoryTransacted()
pouvant être invoquée via l'appel de plate-forme.Pour ce faire, je me suis adapté Mohammad Elsheimy's code pour appeler 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());
}
Dim NewFolder = System.IO.Directory.CreateDirectory(IO.Path.Combine(IO.Path.GetTempPath, Guid.NewGuid.ToString))
@JonathanWright suggère CreateDirectory échouera quand il y a déjà un dossier. Si je lis Directory.CreateDirectory, il est dit 'Cet objet est retourné, que le répertoire du chemin spécifié existe ou non.' Ce qui signifie que vous ne détectez pas un dossier créé entre la vérification existe et la création en cours.
J'aime le CreateDirectoryTransacted() suggéré par @DanielTrebbien mais cette fonction est obsolète.
La seule solution qui reste à faire est d'utiliser le cappi et d'y appeler le 'CreateDirectory' car il y a une erreur si le dossier existe si vous devez vraiment être sûr de couvrir toute la condition de la course. Il en résulterait quelque chose comme ceci:
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
Une vérification de la boucle à l'infini serait judicieuse. – Matt
- 1. Création de dossiers cachés
- 2. Dossiers de création et de ressources Xcode
- 3. Création de fichiers temporaires publics avec un délai d'expiration
- 4. Problème dans la création de fichiers temporaires dans Android?
- 5. la création de dossiers dans IMAP ne fonctionne pas
- 6. SQL Server 2005 Tableaux temporaires
- 7. Nettoyage des rapports SSRS temporaires
- 8. Tables temporaires et réplication SQL Server
- 9. Fichiers temporaires dans .Net
- 10. Fichiers temporaires XMLPad
- 11. Impossible de créer des fichiers temporaires lors de la compilation
- 12. Surveillance de fichiers/dossiers
- 13. Dossiers d'installation de Windows
- 14. Suppression des "fichiers Internet temporaires" de Java
- 15. Elimination des fichiers temporaires ASP.Net
- 16. Entity Framework et objets temporaires
- 17. Tables temporaires persistantes dans SQL?
- 18. Entités temporaires avec Entity Framework
- 19. Hiérarchie de dossiers ASP MVC
- 20. Tables temporaires et performances SQL SELECT
- 21. Utilisation des tables temporaires dans SSIS
- 22. Fichiers temporaires Java et suppression automatique
- 23. Enregistrer les paramètres Ajax temporaires dans jQuery
- 24. Différents dossiers IMAP?
- 25. Tomcat - Dossiers webapps multiples
- 26. Dossiers dans umbraco 4
- 27. Dossiers d'assemblage mono?
- 28. Application de programmation Windows et écriture de fichiers temporaires
- 29. Sous-domaines et dossiers
- 30. SSIS Deployment Utility - Spécification de différents dossiers dans MSDB
Votre condition de boucle ne devrait pas inclure 'File.Exists' en plus de' Directory.Exists'? Il pourrait exister un _file_ temporaire dans Path.GetTempPath, ce qui empêcherait la création d'un répertoire. –
Vous avez raison. Je vais mettre à jour la réponse pour inclure une vérification File.Exists() – Rick
Vous devez ** créer ** le dossier dans la fonction - pour la même raison que GetTempFileName crée le fichier: pour s'assurer qu'il n'y a aucune chance que quelqu'un d'autre le fasse. – Jaykul