@ Chris. Auch ich war besessen von dem Risiko, dass ein temporäres Verzeichnis bereits existiert. Die Diskussionen über zufällig und kryptografisch stark befriedigen mich auch nicht ganz.
Mein Ansatz baut auf der fundamentalen Tatsache auf, dass das Betriebssystem nicht zulassen darf, dass zwei Aufrufe eine Datei erstellen, damit beide erfolgreich sind. Es ist ein wenig überraschend, dass .NET-Designer die Win32-API-Funktionalität für Verzeichnisse ausgeblendet haben, was dies erheblich vereinfacht, da beim zweiten Versuch, ein Verzeichnis zu erstellen, ein Fehler zurückgegeben wird. Folgendes benutze ich:
[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;
}
Sie können entscheiden, ob sich die "Kosten / Risiken" von nicht verwaltetem P / Invoke-Code lohnen. Die meisten würden sagen, dass dies nicht der Fall ist, aber zumindest haben Sie jetzt die Wahl.
CreateParentFolder () wird dem Schüler als Übung überlassen. Ich benutze Directory.CreateDirectory (). Achten Sie darauf, dass Sie das übergeordnete Verzeichnis eines Verzeichnisses abrufen, da es im Stammverzeichnis null ist.