Tworzenie folderów tymczasowych

Pracuję nad programem, który musi utworzyć wiele tymczasowych folderów dla aplikacji. Nie będą one widoczne dla użytkownika. Aplikacja jest napisana w VB.net. mogę wymyślić kilka sposobów, aby to zrobić, takich jak przyrostowa nazwa folderu lub losowe numerowane nazwy folderów, ale zastanawiałem się, jak inni ludzie rozwiązać ten problem?

 29
Author: Dan Halbert, 2008-08-19

13 answers

Update: Dodany Plik.Exists check per comment (2012-Jun-19)

Oto co wykorzystałem w VB.NET. zasadniczo taki sam jak prezentowany, z tym, że zwykle nie chciałem tworzyć folderu od razu.

Zaletą używaniaGetRandomFilename jest to, że nie tworzy pliku, więc nie musisz sprzątać, jeśli używasz nazwy dla czegoś innego niż plik. Jak używanie go do nazwy folderu.

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

Random Nazwa Pliku Przykład:

C:\Documents and Settings\username\Local Settings\Temp \ U3z5e0co.tvq


Oto odmiana używająca Guid, aby uzyskać nazwę folderu tymczasowego.

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 Przykład:

C:\Documents and Settings\username\Local Settings\Temp \ 2dbc6db7-2d45-4b75-b27f-0bd492c60496

 26
Author: Rick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 04:13:54

Musisz użyć System.IO.Path.GetTempFileName()

Tworzy unikalnie nazwany, zerowy bajtowy plik tymczasowy na dysku i zwraca pełną ścieżkę do tego pliku.

Możesz użyć System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName()), Aby uzyskać tylko informacje o folderze tymczasowym i utworzyć tam swoje foldery

Są one tworzone w folderze Windows temp i jest to najlepsza praktyka

 20
Author: juan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-19 18:19:31

Dla wyjaśnienia:

System.IO.Path.GetTempPath()

Zwraca tylko ścieżkę do folderu tymczasowego.

System.IO.Path.GetTempFileName()

Zwraca w pełni kwalifikowaną nazwę pliku (wraz ze ścieżką) tak więc:

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

Jest zbędny.

 8
Author: urini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 18:24:07

Istnieje możliwy stan rasy, gdy:

  • tworzenie pliku tymczasowego z GetTempFileName(), usuwanie go i tworzenie folderu o tej samej nazwie, lub
  • użycie GetRandomFileName() lub Guid.NewGuid.ToString do nazwania folderu i utworzenia go później

Z GetTempFileName() po usunięciu, inna aplikacja może z powodzeniem utworzyć plik tymczasowy o tej samej nazwie. CreateDirectory() wtedy by się nie powiodło.

Podobnie, pomiędzy wywołaniem GetRandomFileName() a utworzeniem katalogu inny proces może utworzyć plik lub katalog o tej samej nazwie, co powoduje awarię CreateDirectory().

Dla większości aplikacji jest OK, aby Katalog temp nie działał ze względu na stan wyścigu. To jednak niezwykle rzadkie. Dla nich te rasy często mogą być ignorowane.

W świecie skryptów powłoki Unix, tworzenie plików tymczasowych i katalogów w bezpieczny sposób wolny od ras jest wielką sprawą. Wiele maszyn ma wielu (wrogich) użytkowników-think shared web host - a wiele skryptów i aplikacji musi bezpiecznie tworzyć temp pliki i katalogi w udostępnionym katalogu / tmp. Zobacz bezpieczne tworzenie plików tymczasowych w skryptach powłoki aby dowiedzieć się, jak bezpiecznie tworzyć katalogi tymczasowe ze skryptów powłoki.

 8
Author: Jonathan Wright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 00:02:07

Jak zauważył @ JonathanWright , istnieją warunki rasowe dla rozwiązań:

  • Utwórz plik tymczasowy za pomocą GetTempFileName(), usuń go i utwórz folder o tej samej nazwie
  • Użyj GetRandomFileName() lub Guid.NewGuid.ToString, aby utworzyć losową nazwę folderu, sprawdź, czy istnieje, a jeśli nie, utwórz ją.

Możliwe jest jednak utworzenie unikalnego katalogu tymczasowego przy użyciu interfejsu API Transactional NTFS (TXF).

TxF ma CreateDirectoryTransacted() funkcja, którą można wywołać poprzez wywołanie Platformy. W tym celu zaadaptowałem kod do wywołania 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
Author: Daniel Trebbien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:13

Coś w tym stylu...

using System.IO;

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

Directory.CreateDirectory(path);
 3
Author: Adam Wright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-19 18:28:30

Możesz wygenerować GUID dla tymczasowych nazw folderów.

 2
Author: Andrew Rimmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-19 18:18:12

Możesz użyć GetTempFileName, aby utworzyć tymczasowy plik , a następnie usunąć i ponownie utworzyć ten plik jako katalog.

Uwaga: link nie działa, Kopiuj / Wklej z: http://msdn.microsoft.com/en-us/library/aa364991 (VS.85). aspx

 2
Author: pix0r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-19 18:19:03

Dopóki nazwa folderu nie musi być znacząca, co powiesz na użycie dla nich GUID?

 1
Author: jwalkerjr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-19 18:18:02

Połączone odpowiedzi od @ adam-wright i pix0r będą działać najlepiej IMHO:


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
Author: Brian G Swanson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-19 18:35:49

Zaletą używania System.IO. Path. GetTempFileName jest to, że będzie to plik w lokalnej ścieżce użytkownika (tzn. nie roamingowej). To jest dokładnie tam, gdzie chcesz go ze względów uprawnień i bezpieczeństwa.

 0
Author: denis phillips,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-19 18:39:10
Dim NewFolder = System.IO.Directory.CreateDirectory(IO.Path.Combine(IO.Path.GetTempPath, Guid.NewGuid.ToString))
 0
Author: jri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-02 19:35:10

@JonathanWright sugeruje, że CreateDirectory zawiedzie, gdy istnieje już folder. Jeśli przeczytam Katalog.CreateDirectory mówi 'obiekt ten jest zwracany niezależnie od tego, czy katalog na podanej ścieżce już istnieje."Oznacza to, że nie wykrywa się folderu utworzonego między sprawdzeniem istnienia a rzeczywistym tworzeniem.

Podoba mi się metoda CreateDirectoryTransacted () zasugerowana przez @ DanielTrebbien, ale ta funkcja jest przestarzała.

Jedyne rozwiązanie jakie widzę to użycie c api i wywołaj tam 'CreateDirectory ', ponieważ robi błąd, jeśli folder istnieje, jeśli naprawdę musisz mieć pewność, że obejmujesz cały stan wyścigu. To skutkowałoby czymś takim:

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
Author: Wilco BT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-13 10:20:37