Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a directory, but fail if it already exists

Tags:

c#

.net

directory

The standard .NET Directory.CreateDirectory(string path) method creates a directory (including parent directories, if needed), if they don't already exists, and returns a DirectoryInfo object for the created directory.

And if the directory does already exist, it returns a DirectoryInfo object for the directory that was already there.

I need a method that will create a directory, if it doesn't already exist, but will fail - returning an error or throwing an exception - if the directory already exists.

And no, Directory.Exists(string path) will not serve. I need something that is atomic. I'm interfacing with C++ apps that were designed to the the presence or absence of certain directories as locks, and doing DirectoryExists() followed by Directory.CreateDirectory() leaves a window that can be stepped on.

At the filesystem level, creating a directory is an atomic operation. If two processes both attempt it, only one will succeed. And the API available to C++ programs reflects this. The standard API in .NET hides this. Is there some lower-level API that is available that does not?

like image 731
Jeff Dege Avatar asked Mar 19 '23 17:03

Jeff Dege


1 Answers

Consider using native CreateDirectory via 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);
}

If it fails because the directory exists, the function returns false and Marshal.GetLastWin32Error should return ERROR_ALREADY_EXISTS (decimal 183 or 0xB7).

ERROR_ALREADY_EXISTS The specified directory already exists.

Please note @stijn's remark however:

Small caveat: CreateDirectory also returns if lpPathName points to an existing file so one might wrongly assume it is a directory.

like image 130
AlexD Avatar answered Mar 21 '23 06:03

AlexD