diff --git a/src/NAppUpdate.Framework/Tasks/FileUpdateTask.cs b/src/NAppUpdate.Framework/Tasks/FileUpdateTask.cs
index 61278b5a..ba9f82da 100644
--- a/src/NAppUpdate.Framework/Tasks/FileUpdateTask.cs
+++ b/src/NAppUpdate.Framework/Tasks/FileUpdateTask.cs
@@ -76,15 +76,21 @@ public override TaskExecutionStatus Execute(bool coldRun)
}
var dirName = Path.GetDirectoryName(_destinationFile);
+
if (!Directory.Exists(dirName))
+ {
Utils.FileSystem.CreateDirectoryStructure(dirName, false);
+ }
// Create a backup copy if target exists
if (_backupFile == null && File.Exists(_destinationFile))
{
if (!Directory.Exists(Path.GetDirectoryName(Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath))))
- Utils.FileSystem.CreateDirectoryStructure(
- Path.GetDirectoryName(Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath)), false);
+ {
+ string backupPath = Path.GetDirectoryName(Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath));
+ Utils.FileSystem.CreateDirectoryStructure(backupPath, false);
+ }
+
_backupFile = Path.Combine(UpdateManager.Instance.Config.BackupFolder, LocalPath);
File.Copy(_destinationFile, _backupFile, true);
}
@@ -94,11 +100,7 @@ public override TaskExecutionStatus Execute(bool coldRun)
{
if (File.Exists(_destinationFile))
{
- //if (FileSystem.IsExeRunning(_destinationFile))
- //{
- // UpdateManager.Instance.Logger.Log(Logger.SeverityLevel.Warning, "Process {0} is still running", _destinationFile);
- // Thread.Sleep(1000); // TODO: retry a few times and throw after a while
- //}
+ FileLockWait();
if (!PermissionsCheck.HaveWritePermissionsForFileOrFolder(_destinationFile))
{
@@ -114,7 +116,10 @@ public override TaskExecutionStatus Execute(bool coldRun)
try
{
if (File.Exists(_destinationFile))
+ {
File.Delete(_destinationFile);
+ }
+
File.Move(_tempFile, _destinationFile);
_tempFile = null;
}
@@ -155,5 +160,23 @@ public override bool Rollback()
return true;
}
+
+ ///
+ /// To mitigate problems with the files being locked even though the application mutex has been released.
+ /// https://github.com/synhershko/NAppUpdate/issues/35
+ ///
+ private void FileLockWait()
+ {
+ int attempt = 0;
+ while (FileSystem.IsFileLocked(new FileInfo(_destinationFile)))
+ {
+ Thread.Sleep(500);
+ attempt++;
+ if (attempt == 10)
+ {
+ throw new UpdateProcessFailedException("Failed to update, the file is locked: " + _destinationFile);
+ }
+ }
+ }
}
}
diff --git a/src/NAppUpdate.Framework/Utils/FileSystem.cs b/src/NAppUpdate.Framework/Utils/FileSystem.cs
index 4e5ba459..3cfdde43 100644
--- a/src/NAppUpdate.Framework/Utils/FileSystem.cs
+++ b/src/NAppUpdate.Framework/Utils/FileSystem.cs
@@ -65,16 +65,36 @@ public static IEnumerable GetFiles(string path, string searchPattern, Se
return files;
}
- public static bool IsExeRunning(string path)
+ ///
+ /// Returns true if read/write lock exists on the file, otherwise false
+ /// From http://stackoverflow.com/a/937558
+ ///
+ /// The file to check for a lock
+ ///
+ public static bool IsFileLocked(FileInfo file)
{
- var processes = Process.GetProcesses();
- foreach (Process p in processes)
+ FileStream stream = null;
+
+ try
+ {
+ stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
+ }
+ catch (IOException)
{
- if (p.MainModule.FileName.StartsWith(path, StringComparison.InvariantCultureIgnoreCase))
- return true;
+ //the file is unavailable because it is:
+ //still being written to
+ //or being processed by another thread
+ //or does not exist (has already been processed)
+ return true;
}
+ finally
+ {
+ if (stream != null)
+ stream.Close();
+ }
+
+ //file is not locked
return false;
}
-
}
}