Ric*_*ick 27
更新:添加了File.Exists检查每条评论(2012年6月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
Run Code Online (Sandbox Code Playgroud)
随机文件名示例:
C:\ Documents and 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
Run Code Online (Sandbox Code Playgroud)
guid示例:
C:\ Documents and Settings\username\Local Settings\Temp\2dbc6db7-2d45-4b75-b27f-0bd492c60496
jua*_*uan 20
你必须使用 System.IO.Path.GetTempFileName()
在磁盘上创建唯一命名的零字节临时文件,并返回该文件的完整路径.
您可以使用System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName())仅获取临时文件夹信息,并在其中创建文件夹
它们是在windows temp文件夹中创建的,这是最佳实践
只是为了澄清:
System.IO.Path.GetTempPath()
Run Code Online (Sandbox Code Playgroud)
只返回临时文件夹的文件夹路径.
System.IO.Path.GetTempFileName()
Run Code Online (Sandbox Code Playgroud)
返回完全限定的文件名(包括路径),这样:
System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetTempFileName())
Run Code Online (Sandbox Code Playgroud)
是多余的.
在以下情况下可能存在竞争条件:
GetTempFileName(),删除它,并创建一个具有相同名称的文件夹,或GetRandomFileName()或Guid.NewGuid.ToString命名文件夹并稍后创建文件夹在GetTempFileName()发生删除之后,另一个应用程序可以成功创建具有相同名称的临时文件.在CreateDirectory()随后会失败.
同样,在调用GetRandomFileName()和创建目录之间,另一个进程可能会创建一个具有相同名称的文件或目录,从而再次导致CreateDirectory()失败.
对于大多数应用程序,临时目录由于竞争条件而失败是可以的.毕竟这是非常罕见的.对他们来说,这些比赛经常被忽略.
在Unix shell脚本世界中,以安全的无竞争方式创建临时文件和目录是一件大事.许多机器具有多个(恶意)用户 - 认为共享Web主机 - 并且许多脚本和应用程序需要在shared/tmp目录中安全地创建临时文件和目录.有关如何从shell脚本安全地创建临时目录的讨论,请参阅在Shell脚本中安全地创建临时文件.
正如@JonathanWright 指出的那样,解决方案存在竞争条件:
GetTempFileName(),删除它,并创建一个具有相同名称的文件夹GetRandomFileName()或Guid.NewGuid.ToString创建随机文件夹名称,检查它是否存在,如果不存在则创建它.但是,可以通过使用Transactional NTFS(TxF)API 以原子方式创建唯一的临时目录.
TxF有一个CreateDirectoryTransacted()可以通过Platform Invoke调用的函数.为此,我调整了Mohammad Elsheimy的电话代码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());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
26274 次 |
| 最近记录: |