@Chris. Ja również miałem obsesję na punkcie zdalnego ryzyka, że katalog tymczasowy może już istnieć. Dyskusje o losowości i silnych kryptograficznie również mnie nie satysfakcjonują.
Moje podejście opiera się na podstawowym fakcie, że system operacyjny nie może pozwolić 2 wywołaniom na utworzenie pliku, aby oba zakończyły się pomyślnie. Trochę zaskakujące jest to, że projektanci .NET zdecydowali się ukryć funkcjonalność Win32 API dla katalogów, co znacznie to ułatwia, ponieważ zwraca błąd, gdy próbujesz utworzyć katalog po raz drugi. Oto czego używam:
[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;
}
To Ty decydujesz, czy „koszt / ryzyko” niezarządzanego kodu p / invoke jest tego warte. Większość powie, że tak nie jest, ale przynajmniej masz teraz wybór.
CreateParentFolder () pozostaje jako ćwiczenie dla ucznia. Używam Directory.CreateDirectory (). Uważaj, aby uzyskać katalog nadrzędny, ponieważ w katalogu głównym jest on pusty.