Сведения о вопросе

Life

15:16, 18th August, 2020

Теги

.net   io    

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

Просмотров: 492   Ответов: 13

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



  Сведения об ответе

SKY

11:05, 23rd August, 2020

Update: добавлена проверка 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 и Settings\username\Local 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 и Settings\username\Local Settings\Temp\2dbc6db7-2d45-4b75-b27f-0bd492c60496


  Сведения об ответе

+-*/

15:22, 25th August, 2020

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

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

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

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


  Сведения об ответе

COOL

08:43, 14th August, 2020

Просто чтобы уточнить:

System.IO.Path.GetTempPath()

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

System.IO.Path.GetTempFileName()

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

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

это излишне.


  Сведения об ответе

PAGE

12:10, 29th August, 2020

Существует возможное состояние гонки, когда:

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

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

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

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

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


  Сведения об ответе

VERSUION

02:24, 17th August, 2020

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

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

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

TxF имеет функцию CreateDirectoryTransacted(),которая может быть вызвана через вызов платформы. Для этого я адаптировал код Мохаммада Эльшейми для вызова 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());
}


  Сведения об ответе

JUST___

11:04, 23rd August, 2020

Что-то вроде этого...

using System.IO;

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

Directory.CreateDirectory(path);


  Сведения об ответе

9090

02:45, 8th August, 2020

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


  Сведения об ответе

PAGE

09:45, 8th August, 2020

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


  Сведения об ответе

прога

14:03, 12th August, 2020

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

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


  Сведения об ответе

crush

13:48, 24th August, 2020

Комбинированные ответы от @adam-wright и pix0r будут работать лучше всего 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);


  Сведения об ответе

+-*/

17:44, 24th August, 2020

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


  Сведения об ответе

lats

12:51, 2nd August, 2020

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


  Сведения об ответе

SEEYOU

20:53, 1st August, 2020

@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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться