创建一个目录,如果该目录已经存在,则操作失败

4
标准的.NET Directory.CreateDirectory(string path)方法可以创建一个目录(包括父目录,如果需要的话),并为已创建的目录返回一个DirectoryInfo对象。如果该目录已经存在,则返回已存在的目录的DirectoryInfo对象。
我需要一个方法,如果目录不存在,它将创建一个目录,但如果该目录已经存在,则会失败-返回错误或抛出异常。
不是使用Directory.Exists(string path)。我需要一个原子性的方法。我正在与被设计为将某些目录的存在或不存在作为锁的C++应用程序进行交互,使用DirectoryExists()然后Directory.CreateDirectory()会留下可以被其他进程占用的空间。
在文件系统级别上,创建目录是一种原子操作。如果两个进程都尝试这样做,只有一个将成功。可供C++程序使用的API就反映了这一点。.NET中的标准API隐藏了这一点。是否有一些更低级别的API可用,不包含这种情况?
1个回答

7

考虑使用本地CreateDirectory通过Interop

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(十进制183或0xB7)

ERROR_ALREADY_EXISTS指定的目录已经存在。

请注意@stijn的备注:

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


可以。有一点 - 如果您没有指定安全属性,不要传递 null,而应该传递 IntPtr.Zero。 - Jeff Dege
小细节:CreateDirectory 也会返回 lpPathName 指向一个已存在的 文件,因此有可能错误地认为它是一个目录。 - stijn
@stijn 很好的提议,谢谢!我已经将它纳入了答案。 - AlexD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接