29


9

アプリケーション用に複数の一時フォルダを作成する必要があるプログラムに取り組んでいます。 これらはユーザーには見えません。 アプリはVB.netで書かれています。 増分フォルダー名やランダムな番号のフォルダー名など、それを実行する方法をいくつか考えることができますが、他のユーザーがこの問題をどのように解決するのか疑問に思いました。

13 Answer


26


*更新:*コメントごとにFile.Existsチェックを追加した。(2012-Jun-19)

これが私がVB.NETで使ったことです。 私は通常すぐにフォルダを作成したくないということを除いて、基本的に提示されたものと同じです。

http://msdn.microsoft.com/ja-jp/library/system.io.path.getrandomfilename.aspx[GetRandomFilename]を使用する利点は、ファイルを作成しないため、クリーンアップする必要がないことです。ファイル以外の名前を使用している場合はup。 フォルダ名に使うのと同じです。
プライベート関数GetTempFolder()文字列としての薄暗いフォルダ= Path.Combine(Path.GetTempPath、Path.GetRandomFileName)Directory.Exists(フォルダ)またはFile.Exists(フォルダ)folder = Path.Combine(Path.GetTempPath、Path .GetRandomFileName)ループ

戻るフォルダー終了機能

*ランダム*ファイル名の例:

C:\ Documents and Settings \ユーザー名\ローカル設定\ Temp \ u3z5e0co.tvq

'' '' '

これは、一時フォルダ名を取得するためにGuidを使用したバリエーションです。

プライベート関数GetTempFolderGuid()文字列としての薄暗いフォルダパス= Path.Combine(Path.GetTempPath、Guid.NewGuid.ToString)Directory.Exists(フォルダ)またはFile.Exists(フォルダ)folder = Path.Combine(Path.GetTempPath) 、Guid.NewGuid.ToString)ループ

戻るフォルダー終了機能
  • guid *例:

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


20


あなたは `System.IO.Path.GetTempFileName()`を使わなければなりません

_ ディスク上に一意の名前、ゼロバイトの一時ファイルを作成し、そのファイルのフルパスを返します。 _

`System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName())`を使って一時フォルダ情報だけを取得し、そこにフォルダを作成することができます。

それらはwindowsの一時フォルダに作成され、それがベストプラクティスと考えられています


8


明確にするために:

System.IO.Path.GetTempPath()

一時フォルダーへのフォルダーパスのみを返します。

System.IO.Path.GetTempFileName()

パスを含む完全修飾ファイル名を返します。

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

冗長です。


8


次の場合に競合状態が発生する可能性があります。

  • `GetTempFileName()`で一時ファイルを作成し、それを削除して、 同じ名前のフォルダー、または

  • `GetRandomFileName()`または `Guid.NewGuid.ToString`を使用して、 フォルダーとフォルダーの作成

削除が発生した後の `GetTempFileName()`では、別のアプリケーションが同じ名前の一時ファイルを正常に作成することができます。 `CreateDirectory()`は失敗します。

同様に、 `GetRandomFileName()`を呼び出してからディレクトリを作成するまでの間に、別のプロセスが同じ名前のファイルまたはディレクトリを作成し、再度 `CreateDirectory()`が失敗する可能性があります。

ほとんどのアプリケーションでは、競合状態が原因で一時ディレクトリが失敗しても問題ありません。 結局非常にまれです。 彼らにとって、これらの種族はしばしば無視されます。

Unixシェルスクリプトの世界では、安全な競合のない方法で一時ファイルとディレクトリを作成することは大きな問題です。 多くのマシンは複数の(敵対的な)ユーザを持っています - 共有ウェブホストだと思います - そして多くのスクリプトやアプリケーションは安全に一時ファイルとディレクトリをshared / tmpディレクトリに作成する必要があります。 シェルスクリプトから一時ディレクトリを安全に作成する方法については、http://www.linuxsecurity.com/content/view/115462/81/ [シェルスクリプトに一時ファイルを安全に作成する]を参照してください。


6


@JonathanWright https://stackoverflow.com/a/217198/196844 [指摘]のとおり、解決策には競合条件があります。

  • `GetTempFileName()`で一時ファイルを作成し、削除して、 同じ名前のフォルダーを作成します

  • `GetRandomFileName()`または `Guid.NewGuid.ToString`を使用して、 ランダムなフォルダ名、存在するかどうかを確認し、存在しない場合は作成します。

ただし、http://msdn.microsoft.com/en-us/library/windows/desktop/aa363764.aspx [トランザクションNTFS](TxF)APIを使用して、一意の一時ディレクトリを自動的に作成することは可能です。

TxFにはhttp://msdn.microsoft.com/ja-jp/library/windows/desktop/aa363857.aspx [CreateDirectoryTransacted()]関数があり、これはプラットフォームの呼び出しで呼び出すことができます。 これを行うために、私はhttp://www.codeproject.com/Articles/66276/Creating-Transacted-Files-in-Windows-Vista.aspx?display=Print[Mohammad Elsheimy’s code]を `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
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);

///
/// Creates a uniquely-named directory in the directory named by  and returns the path to it.
///
/// Path of a directory in which the temporary directory will be created.
/// The path of the newly-created temporary directory within .
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;
}

///
/// Equivalent to GetTempDirectoryName(Path.GetTempPath()).
///
///
public static string GetTempDirectoryName()
{
    return GetTempDirectoryName(Path.GetTempPath());
}


3


何かのようなもの…​

System.IOを使用します。

文字列path = Path.GetTempPath()Path.GetRandomFileName(); while(Directory.Exists(path))path = Path.GetTempPath()Path.GetRandomFileName();

Directory.CreateDirectory(パス);


2


一時フォルダ名のGUIDを生成することができます。


2


http://msdn.microsoft.com/en-us/library/aa364991(VS.85).aspx[GetTempFileName]を使用して一時的な*ファイル*を作成してから、そのファイルを削除してディレクトリとして再作成することができます。 。

注:リンクが機能しませんでした。コピー/貼り付け先:http://msdn.microsoft.com/ja-jp/library/aa364991(VS.85).aspx


1


フォルダーの名前を意味のあるものにする必要がない限り、それらにGUIDを使用してはどうでしょうか。


1


@ adam-wrightとpix0rからの回答を組み合わせたものが、私見にぴったりのものになるでしょう。

System.IOを使用します。

文字列path = Path.GetTempPath()Path.GetRandomFileName();

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

File.Delete(パス)。 Directory.CreateDirectory(パス);