diff --git a/Mo3ModManager/IO.cs b/Mo3ModManager/IO.cs
index b55a630..2a898e9 100644
--- a/Mo3ModManager/IO.cs
+++ b/Mo3ModManager/IO.cs
@@ -113,13 +113,26 @@ public static bool RemoveEmptyFolders(string directory)
}
+ ///
+ /// Create hard links for every files, just like copying folders.
+ ///
+ /// The source folder.
+ /// The destination folder.
+ public static void CreateHardLinksOfFiles(string SrcDirectory, string DestDirectory)
+ {
+ CreateHardLinksOfFiles(SrcDirectory, DestDirectory, false, null);
+ }
///
/// Create hard links for every files, just like copying folders.
///
/// The source folder.
/// The destination folder.
/// Whether override files if exist
- public static void CreateHardLinksOfFiles(string SrcDirectory, string DestDirectory, bool Override = false)
+ public static void CreateHardLinksOfFiles(string SrcDirectory, string DestDirectory, bool Override)
+ {
+ CreateHardLinksOfFiles(SrcDirectory, DestDirectory, Override);
+ }
+ public static void CreateHardLinksOfFiles(string SrcDirectory, string DestDirectory, bool Override, List skipExtensionsWithDotUpper)
{
Debug.WriteLine("Source: " + SrcDirectory);
//Create all folders
@@ -137,21 +150,46 @@ public static void CreateHardLinksOfFiles(string SrcDirectory, string DestDirect
{
string relativeName = srcFullName.Substring(SrcDirectory.Length + 1);
string destFullName = Path.Combine(DestDirectory, relativeName);
- if (!File.Exists(destFullName))
+
+ CreateHardLinkOrCopy(destFullName, srcFullName, Override, skipExtensionsWithDotUpper);
+ //if (!File.Exists(destFullName))
+ //{
+ // Win32.NativeMethods.CreateHardLinkW(destFullName, srcFullName, IntPtr.Zero);
+ //}
+ //else
+ //{
+ // if (Override)
+ // {
+ // //File exists
+ // Debug.WriteLine("Overrided: " + relativeName);
+ // File.Delete(destFullName);
+ // Win32.NativeMethods.CreateHardLinkW(destFullName, srcFullName, IntPtr.Zero);
+ // }
+ //}
+ }
+ }
+
+ private static void CreateHardLinkOrCopy(string destFile, string srcFile, bool Override, List skipExtensionsWithDot)
+ {
+ var ext = Path.GetExtension(destFile).ToUpperInvariant();
+ if (File.Exists(destFile) && Override)
+ {
+ Debug.WriteLine("Overrided: " + destFile);
+ File.Delete(destFile);
+ }
+
+ if (!File.Exists(destFile)) {
+
+ if (skipExtensionsWithDot != null && skipExtensionsWithDot.Contains(ext))
{
- Win32.NativeMethods.CreateHardLinkW(destFullName, srcFullName, IntPtr.Zero);
+ File.Copy(srcFile, destFile, Override);
}
else
{
- if (Override)
- {
- //File exists
- Debug.WriteLine("Overrided: " + relativeName);
- File.Delete(destFullName);
- Win32.NativeMethods.CreateHardLinkW(destFullName, srcFullName, IntPtr.Zero);
- }
+ Win32.NativeMethods.CreateHardLinkW(destFile, srcFile, IntPtr.Zero);
}
- }
+ }
+
}
}
diff --git a/Mo3ModManager/MainWindow.xaml b/Mo3ModManager/MainWindow.xaml
index 5636dc2..ef94509 100644
--- a/Mo3ModManager/MainWindow.xaml
+++ b/Mo3ModManager/MainWindow.xaml
@@ -6,7 +6,7 @@
xmlns:local="clr-namespace:Mo3ModManager"
mc:Ignorable="d"
FontSize="14"
- Title="Mental Omega Mod Manager" Height="450" Width="800" Icon="Icon.ico" WindowStartupLocation="CenterScreen">
+ Title="Mental Omega Mod Manager" Height="450" Width="800" Icon="Icon.ico" WindowStartupLocation="CenterScreen" Closing="Window_Closing">
diff --git a/Mo3ModManager/MainWindow.xaml.cs b/Mo3ModManager/MainWindow.xaml.cs
index faa53b2..22d6563 100644
--- a/Mo3ModManager/MainWindow.xaml.cs
+++ b/Mo3ModManager/MainWindow.xaml.cs
@@ -23,7 +23,7 @@ public partial class MainWindow : Window
public MainWindow()
{
- InitializeComponent();
+ this.InitializeComponent();
this.Title += " v" + System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion;
@@ -132,7 +132,7 @@ private void On_ProgProfilesListView_SelectionChanged()
private void ProfilesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
- On_ProgProfilesListView_SelectionChanged();
+ this.On_ProgProfilesListView_SelectionChanged();
}
private void RunButton_Click(object sender, RoutedEventArgs e)
{
@@ -145,7 +145,9 @@ private void RunButton_Click(object sender, RoutedEventArgs e)
//RunningDirectory = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Game-" + Guid.NewGuid().ToString().Substring(0, 8)),
RunningDirectory = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Game"),
- ProfileDirectory = (this.ProfilesListView.SelectedItem as ProfileItem).Directory
+ //ProfileDirectory = (this.ProfilesListView.SelectedItem as ProfileItem).Directory
+ ProfileDirectory = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Profiles", (this.ProfilesListView.SelectedItem as ProfileItem).Name, (this.ModTreeView.SelectedItem as ModItem).Node.ID)
+
};
@@ -245,7 +247,7 @@ private void RenameProfileButton_Click(object sender, RoutedEventArgs e)
}
System.IO.Directory.Move(selectedItem.Directory, newProfilePath);
selectedItem.ReplaceFrom(new ProfileItem(new System.IO.DirectoryInfo(newProfilePath)));
- On_ProgProfilesListView_SelectionChanged();
+ this.On_ProgProfilesListView_SelectionChanged();
}
catch (Exception ex)
{
@@ -361,5 +363,18 @@ private void InstallModButton_Click(object sender, RoutedEventArgs e)
}
}
+
+ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ if (!this.IsEnabled)
+ {
+ var result = System.Windows.MessageBox.Show(this, "Only close Mod Manager when the game has exited, otherwise you will lose your game data. Click \"Yes\" if you do want to exit now.", "Warning",
+ System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Exclamation);
+ if (result != MessageBoxResult.Yes)
+ {
+ e.Cancel = true;
+ }
+ }
+ }
}
}
diff --git a/Mo3ModManager/ModProcessManager.cs b/Mo3ModManager/ModProcessManager.cs
index 4500ffe..cf7b93a 100644
--- a/Mo3ModManager/ModProcessManager.cs
+++ b/Mo3ModManager/ModProcessManager.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -48,7 +49,7 @@ public enum ProcessStatus
/// Note, if a file was deleted and rebuilt, they will be considered as respective files, and the file will be reserved.
///
/// The node
- private void CleanNode(Node Node)
+ private void CleanNode(Node Node,object addition =null)
{
//source and destination is the same with "PrepareNode"
string sourceDirectory = Node.FilesDirectory;
@@ -56,6 +57,11 @@ private void CleanNode(Node Node)
string destinationDirectory = this.RunningDirectory;
//Remove a NTFS hard link is equal to remove a file
+ Exception ex = null;
+ if (addition != null)
+ {
+ ex = (Exception)addition;
+ }
foreach (string srcFullName in Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories))
{
string relativeName = srcFullName.Substring(sourceDirectory.Length + 1);
@@ -66,7 +72,15 @@ private void CleanNode(Node Node)
if (IO.IsSameFile(srcFullName, destFullName))
{
//Debug.WriteLine("Delete file: " + destFullName);
- File.Delete(destFullName);
+ try
+ {
+ File.Delete(destFullName);
+ }
+ catch (Exception e)
+ {
+ ex = e;
+ }
+
}
else
{
@@ -79,7 +93,11 @@ private void CleanNode(Node Node)
//Recursive for its parent
if (!Node.IsRoot)
{
- this.CleanNode(Node.Parent);
+ this.CleanNode(Node.Parent,ex);
+ }
+ if (ex != null)
+ {
+ throw ex;
}
}
@@ -92,7 +110,7 @@ private void PrepareNode(Node Node)
string srcDirectory = Node.FilesDirectory;
string destDirectory = this.RunningDirectory;
- IO.CreateHardLinksOfFiles(srcDirectory, destDirectory);
+ IO.CreateHardLinksOfFiles(srcDirectory, destDirectory, false, new List() { ".INI" });
//Recursive for its parent
if (!Node.IsRoot)
@@ -120,7 +138,7 @@ private void RunStep2_RunAndWait()
/// The working directory.
private void RunStep2_RunAndWait(string Fullname, string Arguments, string WorkingDirectory)
{
- string commandLine = '"' + Fullname + '"' + (Arguments == string.Empty ? string.Empty : ' ' + Arguments);
+ string commandLine = '"' + Fullname + '"' + (String.IsNullOrEmpty(Arguments) ? string.Empty : ' ' + Arguments);
//See : https://blogs.msdn.microsoft.com/oldnewthing/20130405-00/?p=4743
@@ -247,6 +265,10 @@ private void SetCompatibility(string Fullname, string Compatibility)
private void RunStep1_Prepare()
{
+ if (!Directory.Exists(this.ProfileDirectory))
+ {
+ Directory.CreateDirectory(this.ProfileDirectory);
+ }
Trace.WriteLine("[Note] Clearing Running Directory...");
//RunningDirectory should be empty. Delete all of them otherwise
if (Directory.Exists(this.RunningDirectory))
@@ -260,7 +282,7 @@ private void RunStep1_Prepare()
Trace.WriteLine("[Note] Create hard links for profiles...");
//Move profiles
- IO.CreateHardLinksOfFiles(this.ProfileDirectory, this.RunningDirectory);
+ IO.CreateHardLinksOfFiles(this.ProfileDirectory, this.RunningDirectory, false, new List() { ".INI" });
Trace.WriteLine("[Note] Create hard links for game files...");
//Create hard links recursively - from leaf node to root
@@ -272,6 +294,7 @@ private void RunStep1_Prepare()
this.Node.Compatibility);
//TODO: Set the registry to avoid firewall
+
}
private void RunStep3_Clean()
@@ -290,7 +313,7 @@ private void RunStep3_Clean()
{
Trace.WriteLine("[Note] Save profiles...");
//Save profiles
- IO.CreateHardLinksOfFiles(this.RunningDirectory, this.ProfileDirectory, true);
+ IO.CreateHardLinksOfFiles(this.RunningDirectory, this.ProfileDirectory, true, new List() { ".INI" });
}
IO.ClearDirectory(this.RunningDirectory);
@@ -302,44 +325,6 @@ private void RunStep3_Clean()
}
- ///
- /// Do everything to run the game from specified arguments.
- /// Run and wait for user's confirmation that the game has exited. Will block the thread.
- /// This is a workaround for Windows 7 and earlier.
- /// This method MUST be run in the UI thread.
- ///
- /// The parent window of MessageBox.
- public void RunLegacy(System.Windows.Window parent)
- {
- RunStep1_Prepare();
-
- new Process()
- {
- StartInfo = new ProcessStartInfo()
- {
- FileName = Path.Combine(this.RunningDirectory, this.Node.MainExecutable),
- Arguments = this.Node.Arguments,
- WorkingDirectory = this.RunningDirectory
- }
- }.Start();
-
- //sleep for 10s
- System.Threading.Thread.Sleep(10000);
- System.Windows.MessageBox.Show(parent, "You are still running Windows 7 or earlier.\n It's too old so we can't know whether the game has exited or not.\n Click the OK button when the game has exited.",
- "You should consider upgrading to Windows 10", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Exclamation);
- System.Windows.MessageBox.Show(parent, "Only click the OK button when the game has exited.", "Double check",
- System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Exclamation);
-
- Trace.WriteLine("[Note] Game exited.");
-
- //wait for 3s. just in case
- System.Threading.Thread.Sleep(3000);
- RunStep3_Clean();
-
- }
-
-
-
///
/// Do everything to run the game from specified arguments.
/// Run and wait for user's confirmation that the game has exited. Will not block the thread.
@@ -382,6 +367,35 @@ public void RunLegacyAsync(System.Windows.Window parent)
System.Windows.MessageBox.Show(parent, "Only click the OK button when the game has exited.", "Double check",
System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Exclamation);
+ // notice for dumbs
+ for (var i = 0; i < 5; ++i)
+ {
+ Process[] ps = Process.GetProcesses();
+ if (ps.Count() == 0) break;
+
+ foreach (Process p in ps)
+ {
+ string exePath;
+ try {
+ exePath = Path.GetDirectoryName(p.MainModule.FileName);
+ }
+ catch (Exception)
+ {
+ continue;
+ }
+
+ System.Diagnostics.Debug.WriteLine(exePath);
+ System.Diagnostics.Debug.WriteLine(this.RunningDirectory);
+
+ if (this.RunningDirectory.Contains(exePath))
+ {
+ System.Windows.MessageBox.Show(parent, "Only click the OK button when the game has exited.", "Double check",
+ System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Exclamation);
+ break;
+ }
+ }
+ }
+
Trace.WriteLine("[Note] Game exited.");
System.ComponentModel.BackgroundWorker worker2 = new System.ComponentModel.BackgroundWorker();
diff --git a/Mo3ModManager/Properties/AssemblyInfo.cs b/Mo3ModManager/Properties/AssemblyInfo.cs
index da6062c..fe6f93f 100644
--- a/Mo3ModManager/Properties/AssemblyInfo.cs
+++ b/Mo3ModManager/Properties/AssemblyInfo.cs
@@ -52,4 +52,4 @@
// 方法是按如下所示使用“*”: :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.1.0.4")]
+[assembly: AssemblyFileVersion("1.1.0.5")]