/// <summary> /// Fixes switchable file mixups usually caused by a system or DFOCP crash. Does nothing if no problems /// are detected. Note if the game is running with switched files, this method will try to "fix" them /// and fail. /// </summary> /// <param name="wereBroken">Set to true if the files were broken and were fixed. Set to false if /// the files were not broken.</param> /// <exception cref="System.IO.IOException">Something went wrong while trying to fix the mixup.</exception> /// <exception cref="System.ArgumentNullException">One of the properties is null.</exception> public void FixBrokenFiles(out bool wereBroken) { wereBroken = false; NormalFile.ThrowIfNull("FileToSwitch"); CustomFile.ThrowIfNull("FileToSwitchWith"); TempFile.ThrowIfNull("TempFile"); Logging.Log.DebugFormat("Repairing switchable ('{0}', '{1}', '{2}').", NormalFile, CustomFile, TempFile); Action <string, string> move = FileType.GetMoveFunction(); Func <string, bool> exists = FileType.GetExistsFunction(); if (exists(TempFile) && exists(NormalFile)) { wereBroken = true; Logging.Log.DebugFormat("Normal and temp exist."); // Rename FileToSwitch to FileToSwitchWith try { move(NormalFile, CustomFile); Logging.Log.DebugFormat("Moved file at normal location {0} to custom location {1}", NormalFile, CustomFile); } catch (Exception ex) // XXX: Catch specific exceptions { throw new IOException(string.Format("Could not move {0} to {1}. {2}", NormalFile, CustomFile, ex.Message)); } // Rename TempFile to FileToSwitch try { move(TempFile, NormalFile); Logging.Log.DebugFormat("Moved file at temp location {0} to normal location {1}", TempFile, NormalFile); Logging.Log.DebugFormat("Repair complete."); } catch (Exception ex) // XXX: Catch specific exceptions { throw new IOException(string.Format("Could not move {0} to {1}. {2}", TempFile, NormalFile, ex.Message)); } } else if (exists(TempFile) && exists(CustomFile)) { wereBroken = true; Logging.Log.DebugFormat("Custom and temp exist."); // Rename TempFile to FileToSwitch try { move(TempFile, NormalFile); Logging.Log.DebugFormat("Moved file at temp location {0} to normal location {1}", TempFile, NormalFile); } catch (Exception ex) { throw new IOException(string.Format("Could not move {0} to {1}. {2}", TempFile, NormalFile, ex.Message)); } } else { Logging.Log.DebugFormat("Not broken, nothing to repair."); return; } }
/// <summary> /// Moves FileToSwitch to TempFile and FileToSwitchWith to FileToSwitch. If the second move fails, /// the first move is attempted to be undone. /// </summary> /// <returns>A SwitchedFile object you can use to switch back by calling SwitchBack() on it.</returns> /// <exception cref="System.ArgumentNullExcepton">One of the properties is null.</exception> /// <exception cref="System.IO.IOException">The file could not be switched.</exception> public SwitchedFile Switch() { NormalFile.ThrowIfNull("FileToSwitch"); CustomFile.ThrowIfNull("FileToSwitchWith"); TempFile.ThrowIfNull("TempFile"); Logging.Log.DebugFormat("Switching {0} with {1} using {2} as a temporary.", NormalFile, CustomFile, TempFile); Action <string, string> move = FileType.GetMoveFunction(); bool firstMoveSuccessful = false; try { move(NormalFile, TempFile); firstMoveSuccessful = true; Logging.Log.DebugFormat("Moved {0} to {1}.", NormalFile, TempFile); move(CustomFile, NormalFile); Logging.Log.DebugFormat("Moved {0} to {1}.", CustomFile, NormalFile); Logging.Log.DebugFormat("Switch successful."); return(new SwitchedFile(NormalFile, CustomFile, TempFile, FileType)); } catch (Exception ex) { // If the first move was successful, we can probably move it back bool undoSuccess = false; Exception undoError = null; if (firstMoveSuccessful) { try { move(TempFile, NormalFile); undoSuccess = true; } catch (Exception ex2) { undoError = ex2; } } if (!firstMoveSuccessful) { throw new IOException(string.Format( "Could not move {0} to {1}. {2}", NormalFile, TempFile, ex.Message), ex); } else { string undoMessage; if (undoSuccess) { undoMessage = string.Format( "{0} moved back to {1}.", TempFile, NormalFile); } else { undoMessage = string.Format( "{0} could not be moved back to {1}. {2} Files are in an inconsistent state!", TempFile, NormalFile, undoError.Message); } throw new IOException(string.Format( "Could not move {0} to {1}. {2} {3}", CustomFile, NormalFile, ex.Message, undoMessage), ex); } } }