Создание временных папок

Я работаю над программой, которая должна создать несколько временных папок для приложения. Они не будут видны пользователю. Приложение написано на VB.net. Я могу подумать о нескольких способах сделать это, таких как добавочное имя папки или случайное нумерованное имя папки, но мне было интересно, как другие люди решают эту проблему?

19.08.2008 18:14:14
13 ОТВЕТОВ
РЕШЕНИЕ

Обновление: добавлена ​​проверка File.Exists за комментарий (2012-Jun-19)

Вот что я использовал в VB.NET. По сути, то же самое, что представлено, за исключением того, что я обычно не хотел создавать папку немедленно.

Преимущество использования GetRandomFilename заключается в том, что он не создает файл, поэтому вам не нужно выполнять очистку, если вы используете имя для чего-то, кроме файла. Как использовать его для имени папки.

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

Случайное имя файла Пример:

C: \ Documents and Settings \ имя пользователя \ Локальные настройки \ Temp \ u3z5e0co.tvq


Вот вариант с использованием Guid для получения имени временной папки.

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 :

C: \ Documents and Settings \ имя пользователя \ Локальные настройки \ Temp \ 2dbc6db7-2d45-4b75-b27f-0bd492c60496

27
20.06.2012 04:13:54
Не должно ли ваше условие цикла включать File.Existsв дополнение к Directory.Exists? Там может быть существующий темп файла в Path.GetTempPath, и что будет препятствовать созданию каталога.
William Gross 18.06.2012 15:10:53
Ты прав. Я обновлю ответ, чтобы включить проверку File.Exists ()
Rick 20.06.2012 04:11:34
Вы должны создать папку внутри функции - по той же причине, по которой GetTempFileName создает файл: чтобы убедиться, что есть вероятность того, что кто-то другой сделает это.
Jaykul 30.03.2017 02:10:14
Не забудьте сделатьImports System.IO
Richie Bendall 22.06.2018 07:24:26

Пока имя папки не должно быть значимым, как насчет использования GUID для них?

1
19.08.2008 18:18:02

Вы можете сгенерировать GUID для ваших имен временных папок.

2
19.08.2008 18:18:12

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

Примечание: ссылка не работает, скопируйте / вставьте с: http://msdn.microsoft.com/en-us/library/aa364991(VS.85).aspx

1
19.08.2008 18:19:03

Вы должны использовать System.IO.Path.GetTempFileName()

Создает на диске временный файл с нулевым байтом с уникальным именем и возвращает полный путь к этому файлу.

Вы можете использовать, System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName())чтобы получить только информацию о временной папке, и создавать там свои папки

Они создаются во временной папке Windows, и это считается наилучшей практикой

20
19.08.2008 18:19:31
Как НЕ делать это. Вызов System.IO.Path.GetDirectoryNameна System.IO.Path.GetTempFileNameхудшую для замены System.IO.Path.GetTempPath, так как он создает файл , который получает остался позади.
Jaykul 30.03.2017 02:08:12

Что-то типа...

using System.IO;

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

Directory.CreateDirectory(path);
3
19.08.2008 18:28:30
может быть, с try-catch, чтобы снова войти в цикл, если вам не удалось создать каталог ;-)
Jaykul 30.03.2017 02:12:11

Объединенные ответы от @ adam-wright и pix0r будут работать лучше всего ИМХО:


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
19.08.2008 18:35:49

Преимущество использования System.IO.Path.GetTempFileName заключается в том, что это будет файл с локальным (т. Е. Не роуминг) путем пользователя. Это именно то место, где вы хотели бы получить разрешения и соображения безопасности.

0
19.08.2008 18:39:10

Чтобы уточнить:

System.IO.Path.GetTempPath()

возвращает только путь к папке temp.

System.IO.Path.GetTempFileName()

возвращает полное имя файла (включая путь), вот так:

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

избыточно

8
21.08.2008 18:24:07
GetTempPath и GetTempFileName - это 2 совершенно разных метода. GetTempPath просто возвращает местоположение временной папки системы, а GetTempFileName создает временный файл нулевой длины и возвращает полный путь к этому файлу.
Dries Van Hansewijck 14.12.2010 10:04:52

Возможны условия гонки, когда:

  • создание временного файла с GetTempFileName()его удалением и создание папки с тем же именем, или
  • используя GetRandomFileName()или Guid.NewGuid.ToStringдля имени папки и создания папки позже

После GetTempFileName()удаления другое приложение может успешно создать временный файл с тем же именем. Тогда CreateDirectory()бы не получилось.

Аналогично, между вызовом GetRandomFileName()и созданием каталога другой процесс может создать файл или каталог с тем же именем, что снова приведет к CreateDirectory()сбою.

Для большинства приложений это нормально, если временный каталог не работает из-за состояния гонки. Это чрезвычайно редко в конце концов. Для них эти гонки часто можно игнорировать.

В мире сценариев оболочки Unix создание временных файлов и каталогов безопасным способом без гонок является большой проблемой. У многих машин есть несколько (враждебных) пользователей - например, общий веб-хост - и многие сценарии и приложения должны безопасно создавать временные файлы и каталоги в каталоге shared / tmp. См. Безопасное создание временных файлов в сценариях оболочки для обсуждения того, как безопасно создавать временные каталоги из сценариев оболочки.

8
20.10.2008 00:02:07

Как отметил @JonathanWright , для решений существуют условия гонки:

  • Создайте временный файл GetTempFileName(), удалите его и создайте папку с тем же именем
  • Используйте GetRandomFileName()или Guid.NewGuid.ToStringдля создания произвольного имени папки, проверьте, существует ли оно, и создайте его, если нет.

Тем не менее, можно создать уникальный временный каталог атомарно, используя Transactional NTFS (TxF) API.

TxF имеет CreateDirectoryTransacted()функцию, которая может быть вызвана через Platform Invoke. Для этого я адаптировал код Мохаммада Эльсхейми для вызова 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
23.05.2017 12:18:13
Dim NewFolder = System.IO.Directory.CreateDirectory(IO.Path.Combine(IO.Path.GetTempPath, Guid.NewGuid.ToString))
0
2.09.2013 19:35:10

@JonathanWright предлагает создать CreateDirectory, если папка уже есть. Если я читаю Directory.CreateDirectory, он говорит: «Этот объект возвращается независимо от того, существует ли каталог по указанному пути». Это означает, что вы не обнаруживаете папку, созданную между проверкой, существует и фактически создает.

Мне нравится CreateDirectoryTransacted (), предложенный @DanielTrebbien, но эта функция устарела.

Единственное оставшееся решение, которое я вижу, - это использовать c api и вызывать там « CreateDirectory », так как это приводит к ошибке, если папка существует, если вам действительно нужно быть уверенным, что она покрывает все условия гонки. Это приведет к чему-то вроде этого:

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
13.09.2016 10:20:37
Проверка на бесконечный цикл была бы разумной.
Matt 9.11.2017 04:14:28