Skip to content

Commit d0e8ff4

Browse files
authored
Merge pull request #964 from unchihugo/fix/settings-not-saving
Fix settings not saving by retrying replace attempts
2 parents 7db1708 + f85e26b commit d0e8ff4

1 file changed

Lines changed: 73 additions & 15 deletions

File tree

‎FluentFlyoutWPF/Classes/Settings/SettingsManager.cs‎

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,34 @@ public static void SaveSettings(string? filePath = null)
162162
}
163163

164164
if (File.Exists(filePath))
165-
{
166-
File.Replace(tempPath, filePath, backupPath, true);
167-
}
165+
_ = Task.Run(async () =>
166+
{
167+
// Run asynchronously to avoid blocking the UI thread
168+
try
169+
{
170+
await TryReplaceSettingsFileAsync(filePath, tempPath, backupPath);
171+
Logger.Info("Settings successfully saved to {0}", filePath);
172+
}
173+
catch (Exception ex)
174+
{
175+
Logger.Error(ex, "Error replacing settings file");
176+
}
177+
finally
178+
{
179+
TryDeleteFileIfExists(tempPath);
180+
}
181+
});
168182
else
169183
{
170-
File.Move(tempPath, filePath, true);
184+
try
185+
{
186+
File.Move(tempPath, filePath, true);
187+
Logger.Info("Settings successfully saved to {0}", filePath);
188+
}
189+
finally
190+
{
191+
TryDeleteFileIfExists(tempPath);
192+
}
171193
}
172194
}
173195
}
@@ -181,19 +203,55 @@ public static void SaveSettings(string? filePath = null)
181203
// if the settings file cannot be saved
182204
Logger.Error(ex, "Error saving settings");
183205
}
184-
finally
206+
}
207+
208+
private async static Task TryReplaceSettingsFileAsync(string filePath, string tempPath, string backupPath)
209+
{
210+
Logger.Debug("Initializing replacing settings file at {0}", filePath);
211+
int maxAttempts = 5;
212+
// The following steps try to avoid issues with file locks and permissions on some systems.
213+
for (int attempts = 1; attempts <= maxAttempts; attempts++)
185214
{
186-
// delete temp file if it still exists
187-
if (File.Exists(tempPath))
215+
try
188216
{
189-
try
190-
{
191-
File.Delete(tempPath);
192-
}
193-
catch (Exception ex)
194-
{
195-
Logger.Error(ex, "Error deleting temporary settings file");
196-
}
217+
File.Replace(tempPath, filePath, backupPath, ignoreMetadataErrors: true);
218+
break;
219+
}
220+
catch (IOException ex) when (attempts < maxAttempts)
221+
{
222+
// if the file is locked, wait and retry
223+
Logger.Warn(ex, "Settings file is locked, retrying...");
224+
Thread.Sleep(75);
225+
}
226+
catch (IOException ex)
227+
{
228+
Logger.Warn(ex, "File.Replace failed after retries, manually replacing...");
229+
ManualReplace(filePath, tempPath, backupPath);
230+
return;
231+
}
232+
}
233+
}
234+
235+
private static void ManualReplace(string filePath, string tempPath, string backupPath)
236+
{
237+
TryDeleteFileIfExists(backupPath);
238+
File.Copy(filePath, backupPath);
239+
TryDeleteFileIfExists(filePath);
240+
File.Move(tempPath, filePath);
241+
}
242+
243+
private static void TryDeleteFileIfExists(string path)
244+
{
245+
// delete file if it still exists
246+
if (File.Exists(path))
247+
{
248+
try
249+
{
250+
File.Delete(path);
251+
}
252+
catch (Exception ex)
253+
{
254+
Logger.Error(ex, "Error deleting file at {0}", path);
197255
}
198256
}
199257
}

0 commit comments

Comments
 (0)