diff --git a/NetchUpdater/NetchUpdater.csproj b/NetchUpdater/NetchUpdater.csproj index 9bdbb0cb..f854a2ee 100644 --- a/NetchUpdater/NetchUpdater.csproj +++ b/NetchUpdater/NetchUpdater.csproj @@ -40,4 +40,20 @@ + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + True + True + Resources.resx + + + diff --git a/NetchUpdater/Program.cs b/NetchUpdater/Program.cs index 61b7a180..a94580f7 100644 --- a/NetchUpdater/Program.cs +++ b/NetchUpdater/Program.cs @@ -1,23 +1,39 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.IO.Compression; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; +using NetchUpdater.Properties; namespace NetchUpdater { internal class Program { + static string UpdaterFullName; + static string UpdaterDirectory; + static string UpdaterFriendlyName; + static Process CurrentProcess; + + static Program() + { + CurrentProcess = Process.GetCurrentProcess(); + UpdaterFullName = CurrentProcess.MainModule.FileName; + UpdaterDirectory = Path.GetDirectoryName(UpdaterFullName); + UpdaterFriendlyName = Path.GetFileName(UpdaterFullName); + } + public static void Main(string[] args) { var result = false; + try { - var currentProcess = Process.GetCurrentProcess(); - if (currentProcess.MainModule == null) + #region Check Arguments + + if (CurrentProcess.MainModule == null) { Console.WriteLine("Current Process MainModule is null"); return; @@ -36,52 +52,60 @@ namespace NetchUpdater return; } - // arg1 zipFile - string zipFile; - if (!File.Exists(zipFile = Path.GetFullPath(args[1]))) + var updateExtracted = true; + // arg1 update File/Directory + var updatePath = Path.GetFullPath(args[1]); + if (File.Exists(updatePath)) { - Console.WriteLine("arg1 Zip file Not found"); + updateExtracted = false; + } + else if (!Directory.Exists(updatePath)) + { + Console.WriteLine("arg1 update file/directory Not found"); return; } // arg2 target Directory - string targetDir; - if (!File.Exists(Path.Combine(targetDir = Path.GetFullPath(args[2]), "Netch.exe"))) + string targetPath; + if (!File.Exists(Path.Combine(targetPath = Path.GetFullPath(args[2]), "Netch.exe"))) { Console.Write("arg2 Netch Directory doesn't seems right"); return; } - // check updater directory - var updaterFullName = currentProcess.MainModule.FileName; - var updaterDirectory = Path.GetDirectoryName(updaterFullName); - var updaterFriendlyName = Path.GetFileName(updaterFullName); + #region if under target Directory,then rerun in temp directory - if (File.Exists(Path.Combine(updaterDirectory, "Netch.exe"))) + if (UpdaterDirectory.StartsWith(targetPath)) { // Updater 在目标目录下 // 将程序复制到临时目录,传递参数 var tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var newUpdaterPath = Path.Combine(tempPath, updaterFriendlyName); + var newUpdaterPath = Path.Combine(tempPath, UpdaterFriendlyName); Directory.CreateDirectory(tempPath); - File.Copy(updaterFullName, newUpdaterPath); + File.Copy(UpdaterFullName, newUpdaterPath); Process.Start(new ProcessStartInfo { FileName = newUpdaterPath, - Arguments = $"{args[0]} {args[1]} {args[2]}", + Arguments = $"{port} {updatePath} {targetPath}", + WorkingDirectory = tempPath, UseShellExecute = false }); result = true; return; } - /*if (!Debugger.IsAttached) + #endregion + + #endregion + + /*while (!Debugger.IsAttached) { Console.WriteLine("Waiting Attach"); Thread.Sleep(1000); }*/ - // Let Netch Exit + #region Send Netch Exit command + Process[] _; if ((_ = Process.GetProcessesByName("Netch")).Any()) { @@ -111,25 +135,48 @@ namespace NetchUpdater } } - Thread.Sleep(500); + #endregion - // Extract ZIP - Console.WriteLine("Extract Zip"); - ExtractToDirectory(zipFile, targetDir, true); + var counter = 0; + while (!TestFileFree(Path.Combine(targetPath, "Netch.exe"))) + { + // wait 5 sec + if (counter > 25) + { + Console.WriteLine("Waiting Netch exit timeout"); + return; + } + + Thread.Sleep(200); + counter++; + } + + #region Update + + if (!updateExtracted) + Extract(updatePath, targetPath, true); + else + MoveDirectory(updatePath, targetPath, true); + + #endregion + + #region Finished Update,Start Netch - // Start Netch Console.WriteLine("Start Netch"); Process.Start(new ProcessStartInfo { - FileName = Path.Combine(targetDir, "Netch.exe"), + FileName = Path.Combine(targetPath, "Netch.exe"), UseShellExecute = true, }); + + #endregion + result = true; } catch (Exception e) { if (e is InvalidDataException) - Console.WriteLine("Zip file Broken"); + Console.WriteLine("Archive file Broken"); Console.WriteLine(e.ToString()); } finally @@ -142,30 +189,101 @@ namespace NetchUpdater } } - private static void ExtractToDirectory(string archiveFileName, string destinationDirectoryName, bool overwrite) + private static void Extract(string archiveFileName, string destDirName, bool overwrite) { + archiveFileName = Path.GetFullPath(archiveFileName); + destDirName = Path.GetFullPath(destDirName); + + if (!File.Exists("7za.exe")) + File.WriteAllBytes("7za.exe", Resources._7za); + + var argument = new StringBuilder(); + argument.Append($" x {archiveFileName} -o{destDirName} "); + if (overwrite) + argument.Append(" -y "); + + Process.Start(new ProcessStartInfo + { + UseShellExecute = false, + WindowStyle = ProcessWindowStyle.Hidden, + FileName = Path.GetFullPath("7za.exe"), + Arguments = argument.ToString() + })?.WaitForExit(); + } + + private static void MoveDirectory(string sourceDirName, string destDirName, bool overwrite) + { + sourceDirName = Path.GetFullPath(sourceDirName); + destDirName = Path.GetFullPath(destDirName); if (!overwrite) { - ZipFile.ExtractToDirectory(archiveFileName, destinationDirectoryName); + Directory.Move(sourceDirName, destDirName); } else { - using (var archive = ZipFile.OpenRead(archiveFileName)) + var DirStack = new Stack(); + DirStack.Push(sourceDirName); + + while (DirStack.Count > 0) { - foreach (var file in archive.Entries) + var DirInfo = new DirectoryInfo(DirStack.Pop()); + try { - Console.WriteLine(file.FullName); - var completeFileName = Path.Combine(destinationDirectoryName, file.FullName); - var directory = Path.GetDirectoryName(completeFileName); + foreach (var DirChildInfo in DirInfo.GetDirectories()) + { + try + { + var destPath = DirChildInfo.ToString().Replace(sourceDirName, destDirName); + if (!Directory.Exists(destPath)) + { + Directory.CreateDirectory(destPath); + } + } + catch (Exception e) + { + Console.WriteLine($"Create {DirChildInfo} Folder Error: {e.Message}"); + } - if (!Directory.Exists(directory) && !string.IsNullOrEmpty(directory)) - Directory.CreateDirectory(directory); + DirStack.Push(DirChildInfo.FullName); + } - if (file.Name != "") - file.ExtractToFile(completeFileName, true); + foreach (var FileChildInfo in DirInfo.GetFiles()) + { + try + { + var destPath = FileChildInfo.ToString().Replace(sourceDirName, destDirName); + if (File.Exists(destPath)) + { + File.Delete(destPath); + } + + FileChildInfo.MoveTo(destDirName); + } + catch (Exception e) + { + Console.WriteLine($"Move {FileChildInfo} Error: {e.Message}"); + } + } + } + catch (Exception e) + { + Console.WriteLine($"ERROR:{e.Message}"); } } } } + + private static bool TestFileFree(string FileName) + { + try + { + File.Move(FileName, FileName); + return true; + } + catch + { + return false; + } + } } } \ No newline at end of file diff --git a/NetchUpdater/Properties/Resources.Designer.cs b/NetchUpdater/Properties/Resources.Designer.cs new file mode 100644 index 00000000..0e972568 --- /dev/null +++ b/NetchUpdater/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace NetchUpdater.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NetchUpdater.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Byte[] 类型的本地化资源。 + /// + internal static byte[] _7za { + get { + object obj = ResourceManager.GetObject("7za", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/NetchUpdater/Properties/Resources.resx b/NetchUpdater/Properties/Resources.resx new file mode 100644 index 00000000..628c95de --- /dev/null +++ b/NetchUpdater/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\7za.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NetchUpdater/Resources/7za.exe b/NetchUpdater/Resources/7za.exe new file mode 100644 index 00000000..2bdd57d2 Binary files /dev/null and b/NetchUpdater/Resources/7za.exe differ