C# 在 Windows 中创建临时目录?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/278439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:16:04  来源:igfitidea点击:

Creating a temporary directory in Windows?

c#.netwindowstemporary-directory

提问by Josh Kelley

What's the best way to get a temp directory name in Windows? I see that I can use GetTempPathand GetTempFileNameto create a temporary file, but is there any equivalent to the Linux / BSD mkdtempfunction for creating a temporary directory?

在 Windows 中获取临时目录名称的最佳方法是什么?我看到我可以使用GetTempPathGetTempFileName来创建一个临时文件,但是是否有任何等效于mkdtemp用于创建临时目录的 Linux / BSD功能?

采纳答案by Scott Dorman

No, there is no equivalent to mkdtemp. The best option is to use a combination of GetTempPathand GetRandomFileName.

不,没有相当于 mkdtemp 的东西。最好的选择是结合使用GetTempPathGetRandomFileName

You would need code similar to this:

您将需要与此类似的代码:

public string GetTemporaryDirectory()
{
   string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
   Directory.CreateDirectory(tempDirectory);
   return tempDirectory;
}

回答by Josh Kelley

GetTempPathis the correct way of doing it; I'm not sure what your concern about this method is. You can then use CreateDirectoryto make it.

GetTempPath是正确的做法;我不确定您对这种方法的担忧是什么。然后您可以使用CreateDirectory来制作它。

回答by Chris Rauber

As mentioned above, Path.GetTempPath() is one way to do it. You could also call Environment.GetEnvironmentVariable("TEMP")if the user has a TEMP environment variable set up.

如上所述,Path.GetTempPath() 是一种方法。如果用户设置了 TEMP 环境变量,您还可以调用Environment.GetEnvironmentVariable("TEMP")

If you are planning on using the temp directory as a means of persisting data in the application, you probably should look at using IsolatedStorageas a repository for configuration/state/etc...

如果您计划使用临时目录作为在应用程序中持久保存数据的一种方式,您可能应该考虑使用隔离存储作为配置/状态/等的存储库...

回答by Matthew

I like to use GetTempPath(), a GUID-creation function like CoCreateGuid(), and CreateDirectory().

我喜欢使用 GetTempPath(),一个像 CoCreateGuid() 和 CreateDirectory() 这样的 GUID 创建函数。

A GUID is designed to have a high probability of uniqueness, and it's also highly improbable that someone would manually create a directory with the same form as a GUID (and if they do then CreateDirectory() will fail indicating its existence.)

GUID 被设计为具有很高的唯一性概率,而且有人手动创建与 GUID 形式相同的目录也是极不可能的(如果他们这样做了,那么 CreateDirectory() 将失败表明它的存在。)

回答by Steve Jansen

I hack Path.GetTempFileName()to give me a valid, pseudo-random filepath on disk, then delete the file, and create a directory with the same file path.

我 hackPath.GetTempFileName()在磁盘上给我一个有效的伪随机文件路径,然后删除该文件,并创建一个具有相同文件路径的目录。

This avoids the need for checking if the filepath is available in a while or loop, per Chris' comment on Scott Dorman's answer.

根据 Chris 对 Scott Dorman 的回答的评论,这避免了检查文件路径是否在一段时间或循环中可用的需要。

public string GetTemporaryDirectory()
{
  string tempFolder = Path.GetTempFileName();
  File.Delete(tempFolder);
  Directory.CreateDirectory(tempFolder);

  return tempFolder;
}

If you truly need a cryptographically secure random name, you may want to adapt Scott's answer to use a while or do loop to keep trying to create a path on disk.

如果您确实需要一个加密安全的随机名称,您可能需要调整 Scott 的答案以使用 while 或 do 循环来继续尝试在磁盘上创建路径。

回答by Paulo de Barros

Here is a somewhat more brute-force approach to resolving the collision problem for temporary directory names. It is not an infallible approach, but it reduces significantly the chances of a folder path collision.

这是解决临时目录名称冲突问题的一种更暴力的方法。这不是万无一失的方法,但它显着降低了文件夹路径冲突的可能性。

One could potentially add other process or assembly related information to the directory name to make the collision even less likely, although making such an information visible on the temporary directory name might not be desirable. One could also mix the order with which the time-related fields are combined to make the folder names look more random. I personally prefer to leave it that way simply because it is easier for me to find them all during debugging.

可以潜在地将其他进程或程序集相关信息添加到目录名称,以减少冲突的可能性,尽管在临时目录名称上显示此类信息可能并不理想。还可以混合与时间相关的字段组合的顺序,使文件夹名称看起来更随机。我个人更喜欢保持这种方式,因为我在调试过程中更容易找到它们。

string randomlyGeneratedFolderNamePart = Path.GetFileNameWithoutExtension(Path.GetRandomFileName());

string timeRelatedFolderNamePart = DateTime.Now.Year.ToString()
                                 + DateTime.Now.Month.ToString()
                                 + DateTime.Now.Day.ToString()
                                 + DateTime.Now.Hour.ToString()
                                 + DateTime.Now.Minute.ToString()
                                 + DateTime.Now.Second.ToString()
                                 + DateTime.Now.Millisecond.ToString();

string processRelatedFolderNamePart = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();

string temporaryDirectoryName = Path.Combine( Path.GetTempPath()
                                            , timeRelatedFolderNamePart 
                                            + processRelatedFolderNamePart 
                                            + randomlyGeneratedFolderNamePart);

回答by Andrew Dennison

@Chris. I too was obsessed with the remote risk that a temporary directory might already exist. The discussions about random and cryptographically strong don't completely satisfy me either.

@克里斯。我也沉迷于临时目录可能已经存在的远程风险。关于随机和加密强的讨论也不完全让我满意。

My approach builds on the fundamental fact that the O/S must not allow 2 calls to create a file to both succeed. It is a little surprising that .NET designers chose to hide the Win32 API functionality for directories, which makes this much easier, because it does return an error when you attempt to create a directory for the second time. Here is what I use:

我的方法建立在一个基本事实之上,即 O/S 必须不允许 2 个调用来创建一个文件才能成功。.NET 设计者选择隐藏目录的 Win32 API 功能有点令人惊讶,这使得这更容易,因为当您第二次尝试创建目录时它确实返回错误。这是我使用的:

    [DllImport(@"kernel32.dll", EntryPoint = "CreateDirectory", SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CreateDirectoryApi
        ([MarshalAs(UnmanagedType.LPTStr)] string lpPathName, IntPtr lpSecurityAttributes);

    /// <summary>
    /// Creates the directory if it does not exist.
    /// </summary>
    /// <param name="directoryPath">The directory path.</param>
    /// <returns>Returns false if directory already exists. Exceptions for any other errors</returns>
    /// <exception cref="System.ComponentModel.Win32Exception"></exception>
    internal static bool CreateDirectoryIfItDoesNotExist([NotNull] string directoryPath)
    {
        if (directoryPath == null) throw new ArgumentNullException("directoryPath");

        // First ensure parent exists, since the WIN Api does not
        CreateParentFolder(directoryPath);

        if (!CreateDirectoryApi(directoryPath, lpSecurityAttributes: IntPtr.Zero))
        {
            Win32Exception lastException = new Win32Exception();

            const int ERROR_ALREADY_EXISTS = 183;
            if (lastException.NativeErrorCode == ERROR_ALREADY_EXISTS) return false;

            throw new System.IO.IOException(
                "An exception occurred while creating directory'" + directoryPath + "'".NewLine() + lastException);
        }

        return true;
    }

You get to decide whether the "cost/risk" of unmanaged p/invoke code is worth it. Most would say it is not, but at least you now have a choice.

您可以决定非托管 p/invoke 代码的“成本/风险”是否值得。大多数人会说不是,但至少你现在有一个选择。

CreateParentFolder() is left as an exercise to the student. I use Directory.CreateDirectory(). Be careful getting the parent of a directory, since it is null when at the root.

CreateParentFolder() 留给学生作为练习。我使用 Directory.CreateDirectory()。获取目录的父目录时要小心,因为它在根目录下为空。

回答by Jan Hlavsa

I usually use this:

我通常使用这个:

    /// <summary>
    /// Creates the unique temporary directory.
    /// </summary>
    /// <returns>
    /// Directory path.
    /// </returns>
    public string CreateUniqueTempDirectory()
    {
        var uniqueTempDir = Path.GetFullPath(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
        Directory.CreateDirectory(uniqueTempDir);
        return uniqueTempDir;
    }

If you want to be absolutely sure that this directory name will not exists in temp path then you need to check if this unique directory name exists and try to create other one if it really exists.

如果您想绝对确定临时路径中不存在此目录名称,则需要检查此唯一目录名称是否存在,如果确实存在,则尝试创建另一个目录名称。

But this GUID-based implementation is sufficient. I have no experience with any problem in this case. Some MS applications uses GUID based temp directories too.

但是这种基于 GUID 的实现就足够了。在这种情况下,我没有任何问题的经验。一些 MS 应用程序也使用基于 GUID 的临时目录。