Browse Source

Avoid problems saving files (with safe saving enabled) when the same project is also open in Visual Studio

pull/607/head
Daniel Grunwald 11 years ago
parent
commit
a185188105
  1. 34
      src/Main/Base/Project/Util/NativeMethods.cs
  2. 11
      src/Main/Base/Project/Workbench/File/OpenedFile.cs

34
src/Main/Base/Project/Util/NativeMethods.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
@ -122,6 +123,39 @@ namespace ICSharpCode.SharpDevelop @@ -122,6 +123,39 @@ namespace ICSharpCode.SharpDevelop
}
#endregion
#region SetFileTime
[StructLayout(LayoutKind.Sequential)]
struct FILETIME
{
internal uint ftTimeLow;
internal uint ftTimeHigh;
public FILETIME(long fileTime)
{
unchecked {
this.ftTimeLow = (uint)fileTime;
this.ftTimeHigh = (uint)(fileTime >> 32);
}
}
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
unsafe static extern bool SetFileTime(SafeFileHandle hFile, FILETIME* creationTime, FILETIME* lastAccessTime, FILETIME* lastWriteTime);
/// <summary>
/// Update the file times on the given file handle.
/// </summary>
public unsafe static void SetFileCreationTime(SafeFileHandle hFile, DateTime creationTime)
{
FILETIME fileCreationTime = new FILETIME(creationTime.ToFileTimeUtc());
if (!SetFileTime(hFile, &fileCreationTime, null, null)) {
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
#endregion
#region Get OEM Encoding
[DllImport("kernel32.dll")]
static extern int GetOEMCP();

11
src/Main/Base/Project/Workbench/File/OpenedFile.cs

@ -230,6 +230,14 @@ namespace ICSharpCode.SharpDevelop.Workbench @@ -230,6 +230,14 @@ namespace ICSharpCode.SharpDevelop.Workbench
bool safeSaving = SD.FileService.SaveUsingTemporaryFile && File.Exists(FileName);
string saveAs = safeSaving ? FileName + ".bak" : FileName;
using (FileStream fs = new FileStream(saveAs, FileMode.Create, FileAccess.Write)) {
if (safeSaving) {
// Copy creation time from source file
// Because setting the time requires opening the file for write access,
// we can't use System.IO.File.SetCreationTimeUtc for this, as it would open the file twice,
// which causes problems when another process is monitoring the directory
// and reading our new file as soon as we're done writing.
NativeMethods.SetFileCreationTime(fs.SafeFileHandle, File.GetCreationTimeUtc(FileName));
}
if (currentView != null) {
SaveCurrentViewToStream(fs);
} else {
@ -237,7 +245,7 @@ namespace ICSharpCode.SharpDevelop.Workbench @@ -237,7 +245,7 @@ namespace ICSharpCode.SharpDevelop.Workbench
}
}
if (safeSaving) {
DateTime creationTime = File.GetCreationTimeUtc(FileName);
// TODO: we should probably use Win32 MoveFileEx to atomically move while replacing the old file
File.Delete(FileName);
try {
File.Move(saveAs, FileName);
@ -247,7 +255,6 @@ namespace ICSharpCode.SharpDevelop.Workbench @@ -247,7 +255,6 @@ namespace ICSharpCode.SharpDevelop.Workbench
System.Threading.Thread.Sleep(250);
File.Move(saveAs, FileName);
}
File.SetCreationTimeUtc(FileName, creationTime);
}
IsDirty = false;
}

Loading…
Cancel
Save