public override Stream CreateStream(DiagnosticBag diagnostics)
{
Debug.Assert(_streamToDispose == null);
try
{
try
{
return OpenFileStream();
}
catch (IOException e)
{
// Other process is reading the file preventing us to write to it.
// We attempt to rename and delete the file in case the reader opened it with FileShare.Delete flag that
// allows the file to be deleted by other processes.
//
// Note that if the file is marked "readonly" or the current user doesn't have sufficient privileges
// the exception thrown is UnauthorizedAccessException, not IOException, so we won't attempt to delete the file.
try
{
const int eWin32SharingViolation = unchecked((int)0x80070020);
if (PathUtilities.IsUnixLikePlatform)
{
// Unix & Mac are simple: just delete the file in the directory.
// The memory mapped content remains available for the reader.
File.Delete(_filePath);
}
else if (e.HResult == eWin32SharingViolation)
{
// On Windows File.Delete only marks the file for deletion, but doesn't remove it from the directory.
var newFilePath = Path.Combine(Path.GetDirectoryName(_filePath), Guid.NewGuid().ToString() + "_" + Path.GetFileName(_filePath));
// Try to rename the existing file. This fails unless the file is open with FileShare.Delete.
File.Move(_filePath, newFilePath);
// hide the renamed file:
File.SetAttributes(newFilePath, FileAttributes.Hidden);
// Mark the renamed file for deletion, so that it's deleted as soon as the current reader is finished reading it
File.Delete(newFilePath);
}
}
catch
{
// report the original exception
ReportOpenFileDiagnostic(diagnostics, e);
return null;
}
return OpenFileStream();
}
}
catch (Exception e)
{
ReportOpenFileDiagnostic(diagnostics, e);
return null;
}
}