[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CreateDirectory(string lpPathName,
IntPtr lpSecurityAttributes);
None.
Advantage - Doesn't require the running assembly to have permissions to the entire folder path.
Disadvantage - Only creates the end-most directory, not the full path.
Iteratively Create a Directory Tree
I updated the code in the Microsoft.Esxperimental.IO project (http://bcl.codeplex.com/releases/view/42783) so some of the classes referenced here (NativeMethods, LongPathCommon) are taken from that project.
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);
}
public static void Create(string path)
{
if (String.IsNullOrEmpty(path))
{
throw new ArgumentException("Path cannot be an empty string.");
}
int startPos = 1; // First part of the path to create.
// Split the given string into components which will have to be individually created.
String[] pathComponents = path.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
// Get the first path component, either "c:" or "\\servername".
String partPath = pathComponents[0];
// If the path is a UNC path, then add the share to the initial starting path.
if (partPath.StartsWith(@"\\"))
{
if (pathComponents.Length < 3)
{
throw new ArgumentException("Invalid path specified: " + path);
}
// Add the share name.
partPath = Path.Combine(partPath, pathComponents[1]);
startPos = 2;
}
// If the path is the root of a drive, then add the directoy separator char.
if (partPath.Contains(":"))
{
if (pathComponents.Length < 2)
{
throw new ArgumentException("Invalid path specified: " + path);
}
// Add the directory separator char here since Path.Combine will not add it if a drive specifier (ie: "C:") is given.
// See Remarks in http://msdn.microsoft.com/en-us/library/fyy7a5kt.aspx
// Also see http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#relative%5Fpaths
partPath += Path.DirectorySeparatorChar;
}
// Create the individual path components.
for (int i = startPos; i < pathComponents.Length; i++)
{
// Add the path component to create.
partPath = System.IO.Path.Combine(partPath, pathComponents[i]);
string normalizedPath = LongPathCommon.NormalizeLongPath(partPath, "partPath");
// Create the path.
if (!NativeMethods.CreateDirectory(normalizedPath, IntPtr.Zero))
{
// To mimic Directory.CreateDirectory, we don't throw if the directory (not a file) already exists
int errorCode = Marshal.GetLastWin32Error();
if (errorCode != NativeMethods.ERROR_ALREADY_EXISTS || !LongPathDirectory.Exists(partPath))
{
throw LongPathCommon.GetExceptionFromWin32Error(errorCode);
}
}
}
}
string path = "c:\\test\\newDir";
CreateDirectory(path, IntPtr.Zero);