【问题标题】:Create a directory, but fail if it already exists创建一个目录,但如果它已经存在则失败
【发布时间】:2014-10-08 08:18:52
【问题描述】:

标准的 .NET Directory.CreateDirectory(string path) 方法创建一个目录(包括父目录,如果需要),如果它们不存在,并为创建的目录返回一个 DirectoryInfo 对象。

如果该目录已经存在,它会为已经存在的目录返回一个 DirectoryInfo 对象。

我需要一个方法来创建一个目录,如果它不存在,但会失败 - 返回错误或抛出异常 - 如果目录已经存在。

不,Directory.Exists(string path) 不会提供服务。我需要一些原子的东西。我正在与 C++ 应用程序交互,这些应用程序旨在将某些目录的存在或不存在作为锁定,并且执行 DirectoryExists() 后跟 Directory.CreateDirectory() 会留下一个可以踩到的窗口。

在文件系统级别,创建目录是一个原子操作。如果两个进程都尝试它,那么只有一个会成功。 C++ 程序可用的 API 反映了这一点。 .NET 中的标准 API 隐藏了这一点。是否有一些较低级别的 API 可用但不可用?

【问题讨论】:

    标签: c# .net directory


    【解决方案1】:

    考虑通过Interop使用原生CreateDirectory

    internal static class NativeMethods
    {
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes);
    }
    

    如果因为目录存在而失败,函数返回falseMarshal.GetLastWin32Error应该返回ERROR_ALREADY_EXISTS(decimal 183 or 0xB7)

    ERROR_ALREADY_EXISTS指定的目录已经存在。

    请注意 @stijn 的评论:

    小警告:如果lpPathName 指向现有文件,CreateDirectory 也会返回,因此可能会错误地认为它是一个目录。

    【讨论】:

    • 这行得通。一件事 - 如果你没有指定安全属性,而不是传递 null,传递 IntPtr.Zero。
    • 小警告:如果 lpPathName 指向现有 文件,CreateDirectory 也会返回,因此可能会错误地认为它是一个目录。
    • @stijn 好点,谢谢!我将其合并到答案中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 2018-08-01
    • 2021-09-26
    相关资源
    最近更新 更多