Création de dossiers temporaires

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 en VB.net. Je peux penser à quelques façons de le faire comme le nom de dossier incrémental ou les noms de dossier numérotés au hasard, mais je me demandais, comment d'autres personnes résolvent ce problème?

29
demandé sur Dan Halbert 2008-08-19 22:14:14

13 réponses

mise à Jour: Ajout De Fichier.Il existe de vérifier par commentaire (2012-Jun-19)

voici ce que j'ai utilisé dans VB.NET. Essentiellement le même que présenté, sauf que je ne voulais 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 à nettoyer si vous utilisez le nom pour autre chose qu'un fichier. Comme l'utiliser pour le dossier nom.

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 De Fichier Exemple:


voici une variation en utilisant un Guid pour obtenir le nom du dossier temp.

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:

26
répondu Rick 2012-06-20 04:13:54

Vous devez utiliser System.IO.Path.GetTempFileName()

crée un fichier temporaire à zéro octet nommé de façon unique 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 le dossier temp de l'information et de créer vos dossiers dedans

ils sont créés dans le dossier windows temp et c'est considéré comme une meilleure pratique

20
répondu juan 2008-08-19 18:19:31

Juste pour préciser:

System.IO.Path.GetTempPath()

renvoie juste le chemin du dossier dans le dossier temporaire.

System.IO.Path.GetTempFileName()

renvoie le nom complet du fichier (y compris le chemin) ainsi:

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

est redondante.

8
répondu urini 2008-08-21 18:24:07

il y a une condition de course possible quand:

  • création d'un fichier temporaire avec GetTempFileName(), de l'effacer, et de faire un dossier avec le même nom, ou
  • en utilisant GetRandomFileName() ou Guid.NewGuid.ToString le nom d'un dossier et de créer le dossier plus tard

GetTempFileName() après la suppression se produit, une autre application pourrait créer avec succès un fichier temp avec le même nom. CreateDirectory() serait alors un échec.

de Même, entre l'appel de GetRandomFileName() et la création de le répertoire un autre processus pourrait créer un fichier ou un répertoire avec le même nom, résultant à nouveau en CreateDirectory() échec.

pour la plupart des applications, il est possible qu'un répertoire temporaire échoue en raison d'une condition de course. Il est extrêmement rare, après tout. Pour eux, ces courses peuvent souvent être ignoré.

dans le monde des scripts Unix shell, la création de fichiers et de répertoires temporaires d'une manière sûre et sans course est importante. Beaucoup de machines ont de multiples utilisateurs (hostiles) -- pensez hôte Web partagé -- et de nombreux scripts et applications ont besoin de créer en toute sécurité des fichiers et répertoires temp dans le répertoire shared /tmp. Voir créer en toute sécurité des fichiers temporaires dans des Scripts Shell pour une discussion sur la façon de créer des répertoires temp en toute sécurité à partir de scripts shell.

8
répondu Jonathan Wright 2008-10-20 00:02:07

As @JonathanWright souligné, les conditions de concurrence qui existent pour les solutions:

  • Créer un fichier temporaire avec GetTempFileName(), le supprimer, et de créer un dossier avec le même nom
  • Utiliser GetRandomFileName() ou Guid.NewGuid.ToString pour créer un nom de Dossier aléatoire, Vérifiez s'il existe et créez-le si ce n'est pas le cas.

il est possible, cependant, de créer un répertoire temporaire unique atomiquement en utilisant le NTFS Transactionnels (TxF) API.

TxF a un CreateDirectoryTransacted() fonction qui peut être invoquée via la plate-forme Invoke. Pour ce faire, je me suis adapté le code de Mohammad Elsheimy 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());
}
6
répondu Daniel Trebbien 2017-05-23 12:18:13

quelque Chose comme...

using System.IO;

string path = Path.GetTempPath() + Path.GetRandomFileName();
while (Directory.Exists(path))
 path = Path.GetTempPath() + Path.GetRandomFileName();

Directory.CreateDirectory(path);
3
répondu Adam Wright 2008-08-19 18:28:30

vous pouvez générer un GUID pour vos noms de dossiers temporaires.

2
répondu Andrew Rimmer 2008-08-19 18:18:12

Vous pouvez utiliser GetTempFileName pour créer un temporaire le fichier, puis supprimer et recréer ce fichier en tant que répertoire à la place.

Note: le lien ne fonctionne pas, copier/coller: http://msdn.microsoft.com/en-us/library/aa364991(SV.85).aspx

2
répondu pix0r 2008-08-19 18:19:03

aussi longtemps que le nom du dossier n'a pas besoin d'être significatif, pourquoi ne pas utiliser un GUID pour eux?

1
répondu jwalkerjr 2008-08-19 18:18:02

réponses Combinées de @adam-wright et pix0r travail sera le meilleur à 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);
1
répondu Brian G Swanson 2008-08-19 18:35:49

l'avantage d'utiliser le système.IO.Chemin.GetTempFileName indique que ce sera un fichier dans le chemin local de l'utilisateur (c.-à-d. non-roaming). C'est exactement là que vous le voulez pour des raisons de permissions et de sécurité.

0
répondu denis phillips 2008-08-19 18:39:10
Dim NewFolder = System.IO.Directory.CreateDirectory(IO.Path.Combine(IO.Path.GetTempPath, Guid.NewGuid.ToString))
0
répondu jri 2013-09-02 19:35:10

@JonathanWright suggère que CreateDirectory va échouer quand il y a déjà un dossier. Si j'ai lu l'Annuaire.CreateDirectory dit 'Cet objet est retourné, qu'un répertoire existe ou non sur le chemin spécifié.'Ce qui signifie que vous ne détectez pas un dossier créé entre check exists et creating.

j'aime le CreateDirectoryTransacted () suggéré par @DanielTrebbien mais cette fonction est dépréciée.

La seule solution que je vois qui reste est de utilisez l'api c et appelez le' CreateDirectory ' là comme il fait erreur si le dossier existe si vous avez vraiment besoin d'ê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
0
répondu Wilco BT 2016-09-13 10:20:37