Skip to content

Commit

Permalink
v1.1.0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
SadPencil committed Apr 2, 2020
1 parent 8436c80 commit 5c27856
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 62 deletions.
60 changes: 49 additions & 11 deletions Mo3ModManager/IO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,26 @@ public static bool RemoveEmptyFolders(string directory)
}


/// <summary>
/// Create hard links for every files, just like copying folders.
/// </summary>
/// <param name="SrcDirectory">The source folder.</param>
/// <param name="DestDirectory">The destination folder.</param>
public static void CreateHardLinksOfFiles(string SrcDirectory, string DestDirectory)
{
CreateHardLinksOfFiles(SrcDirectory, DestDirectory, false, null);
}
/// <summary>
/// Create hard links for every files, just like copying folders.
/// </summary>
/// <param name="SrcDirectory">The source folder.</param>
/// <param name="DestDirectory">The destination folder.</param>
/// <param name="Override">Whether override files if exist</param>
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<string> skipExtensionsWithDotUpper)
{
Debug.WriteLine("Source: " + SrcDirectory);
//Create all folders
Expand All @@ -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<string> 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);
}
}
}

}

}
Expand Down
2 changes: 1 addition & 1 deletion Mo3ModManager/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
<Grid>
<DockPanel LastChildFill="True" >
<Grid DockPanel.Dock="Bottom" Margin="5">
Expand Down
23 changes: 19 additions & 4 deletions Mo3ModManager/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
{
Expand All @@ -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)

};


Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
}
}
}
}
104 changes: 59 additions & 45 deletions Mo3ModManager/ModProcessManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -48,14 +49,19 @@ public enum ProcessStatus
/// Note, if a file was deleted and rebuilt, they will be considered as respective files, and the file will be reserved.
/// </summary>
/// <param name="ModItem">The node</param>
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;
Debug.WriteLine(sourceDirectory);
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);
Expand All @@ -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
{
Expand All @@ -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;
}
}

Expand All @@ -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<string>() { ".INI" });

//Recursive for its parent
if (!Node.IsRoot)
Expand Down Expand Up @@ -120,7 +138,7 @@ private void RunStep2_RunAndWait()
/// <param name="WorkingDirectory">The working directory.</param>
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

Expand Down Expand Up @@ -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))
Expand All @@ -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<string>() { ".INI" });

Trace.WriteLine("[Note] Create hard links for game files...");
//Create hard links recursively - from leaf node to root
Expand All @@ -272,6 +294,7 @@ private void RunStep1_Prepare()
this.Node.Compatibility);

//TODO: Set the registry to avoid firewall

}

private void RunStep3_Clean()
Expand All @@ -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<string>() { ".INI" });
}

IO.ClearDirectory(this.RunningDirectory);
Expand All @@ -302,44 +325,6 @@ private void RunStep3_Clean()

}

/// <summary>
/// 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.
/// </summary>
/// <param name="parent">The parent window of MessageBox.</param>
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();

}



/// <summary>
/// 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.
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion Mo3ModManager/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]

0 comments on commit 5c27856

Please sign in to comment.