From be2ee1a5df9b789c6d656250f9fe10d160d11561 Mon Sep 17 00:00:00 2001 From: ChsBuffer <33744752+chsbuffer@users.noreply.github.com> Date: Wed, 12 Aug 2020 02:22:26 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E4=B8=8B=E8=BD=BD=E5=B9=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Netch.sln | 4 + Netch/Controllers/UpdateChecker.cs | 26 ++- Netch/Forms/MainForm.Designer.cs | 47 +++++- Netch/Forms/MainForm.MenuStrip.cs | 22 +++ Netch/Forms/MainForm.Misc.cs | 66 +++++++- Netch/Forms/MainForm.Status.cs | 1 + Netch/Forms/MainForm.cs | 3 + Netch/Models/GitHubRelease/SuffixVersion.cs | 5 + Netch/Netch.cs | 2 + Netch/Netch.csproj | 2 + Netch/Utils/Utils.cs | 15 ++ Netch/Utils/WebUtil.cs | 35 +++- NetchUpdater/.gitignore | 2 + NetchUpdater/NetchUpdater.csproj | 55 +++++++ NetchUpdater/Program.cs | 172 ++++++++++++++++++++ NetchUpdater/Properties/AssemblyInfo.cs | 35 ++++ 16 files changed, 470 insertions(+), 22 deletions(-) create mode 100644 NetchUpdater/.gitignore create mode 100644 NetchUpdater/NetchUpdater.csproj create mode 100644 NetchUpdater/Program.cs create mode 100644 NetchUpdater/Properties/AssemblyInfo.cs diff --git a/Netch.sln b/Netch.sln index 55db768e..2c32b0a9 100644 --- a/Netch.sln +++ b/Netch.sln @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netch", "Netch\Netch.csproj EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetchLib", "NetchLib\NetchLib.csproj", "{A8715AF4-ACC6-43F9-9381-4294C5360623}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetchUpdater", "NetchUpdater\NetchUpdater.csproj", "{828318A8-9B90-4A5F-BD6B-E632CC9D8933}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -21,6 +23,8 @@ Global {A8715AF4-ACC6-43F9-9381-4294C5360623}.Debug|x64.Build.0 = Debug|x64 {A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x64.ActiveCfg = Release|x64 {A8715AF4-ACC6-43F9-9381-4294C5360623}.Release|x64.Build.0 = Release|x64 + {828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Debug|x64.ActiveCfg = Debug|x64 + {828318A8-9B90-4A5F-BD6B-E632CC9D8933}.Debug|x64.Build.0 = Debug|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Netch/Controllers/UpdateChecker.cs b/Netch/Controllers/UpdateChecker.cs index 6f5299f2..5ce0057c 100644 --- a/Netch/Controllers/UpdateChecker.cs +++ b/Netch/Controllers/UpdateChecker.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Threading.Tasks; +using System.Net; using Netch.Models.GitHubRelease; using Netch.Utils; using Newtonsoft.Json; @@ -19,12 +19,13 @@ namespace Netch.Controllers public string LatestVersionNumber; public string LatestVersionUrl; + public string LatestVersionDownloadUrl; public event EventHandler NewVersionFound; public event EventHandler NewVersionFoundFailed; public event EventHandler NewVersionNotFound; - public void Check(bool notifyNoFound, bool isPreRelease) + public void Check(bool isPreRelease) { try { @@ -35,22 +36,31 @@ namespace Netch.Controllers var releases = JsonConvert.DeserializeObject>(json); var latestRelease = VersionUtil.GetLatestRelease(releases, isPreRelease); + LatestVersionNumber = latestRelease.tag_name; + LatestVersionUrl = latestRelease.html_url; + LatestVersionDownloadUrl = latestRelease.assets[0].browser_download_url; + Logging.Info($"Github 最新发布版本: {latestRelease.tag_name}"); if (VersionUtil.CompareVersion(latestRelease.tag_name, Version) > 0) { - LatestVersionNumber = latestRelease.tag_name; - LatestVersionUrl = latestRelease.html_url; + Logging.Info($"发现新版本"); NewVersionFound?.Invoke(this, new EventArgs()); } else { - LatestVersionNumber = latestRelease.tag_name; - if (notifyNoFound) NewVersionNotFound?.Invoke(this, new EventArgs()); + Logging.Info("目前是最新版本"); + NewVersionNotFound?.Invoke(this, new EventArgs()); } } catch (Exception e) { - Logging.Error(e.ToString()); - if (notifyNoFound) NewVersionFoundFailed?.Invoke(this, new EventArgs()); + if (e is WebException) + Logging.Warning($"获取新版本失败: {e.Message}"); + else + { + Logging.Warning(e.ToString()); + } + + NewVersionFoundFailed?.Invoke(this, new EventArgs()); } } } diff --git a/Netch/Forms/MainForm.Designer.cs b/Netch/Forms/MainForm.Designer.cs index 51577262..37611e5b 100644 --- a/Netch/Forms/MainForm.Designer.cs +++ b/Netch/Forms/MainForm.Designer.cs @@ -41,6 +41,7 @@ namespace Netch.Forms this.AddVMessServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.AddTrojanServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.CreateProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -53,8 +54,10 @@ namespace Netch.Forms this.updateACLWithProxyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.reinstallTapDriverToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CheckForUpdatesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.AboutToolStripButton = new System.Windows.Forms.ToolStripButton(); this.VersionLabel = new System.Windows.Forms.ToolStripLabel(); + this.NewVersionLabel = new System.Windows.Forms.ToolStripLabel(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox(); this.configLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); @@ -113,9 +116,11 @@ namespace Netch.Forms this.ModeToolStripMenuItem, this.SubscribeToolStripMenuItem, this.OptionsToolStripMenuItem, + this.HelpToolStripMenuItem, + this.exitToolStripMenuItem, this.AboutToolStripButton, - this.VersionLabel, - this.exitToolStripMenuItem}); + this.NewVersionLabel, + this.VersionLabel}); this.MenuStrip.Location = new System.Drawing.Point(0, 0); this.MenuStrip.Name = "MenuStrip"; this.MenuStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional; @@ -188,6 +193,15 @@ namespace Netch.Forms this.ModeToolStripMenuItem.Size = new System.Drawing.Size(55, 21); this.ModeToolStripMenuItem.Text = "Mode"; // + // HelpToolStripMenuItem + // + this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.CheckForUpdatesToolStripMenuItem}); + this.HelpToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1); + this.HelpToolStripMenuItem.Name = "HelpToolStripMenuItem"; + this.HelpToolStripMenuItem.Size = new System.Drawing.Size(55, 21); + this.HelpToolStripMenuItem.Text = "Help"; + // // CreateProcessModeToolStripMenuItem // this.CreateProcessModeToolStripMenuItem.Name = "CreateProcessModeToolStripMenuItem"; @@ -282,6 +296,13 @@ namespace Netch.Forms this.reinstallTapDriverToolStripMenuItem.Text = "Reinstall TUN/TAP driver"; this.reinstallTapDriverToolStripMenuItem.Click += new System.EventHandler(this.reinstallTapDriverToolStripMenuItem_Click); // + // CheckForUpdatesToolStripMenuItem + // + this.CheckForUpdatesToolStripMenuItem.Name = "CheckForUpdatesToolStripMenuItem"; + this.CheckForUpdatesToolStripMenuItem.Size = new System.Drawing.Size(219, 22); + this.CheckForUpdatesToolStripMenuItem.Text = "Check for updates"; + this.CheckForUpdatesToolStripMenuItem.Click += new System.EventHandler(this.CheckForUpdatesToolStripMenuItem_Click); + // // AboutToolStripButton // this.AboutToolStripButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; @@ -292,6 +313,20 @@ namespace Netch.Forms this.AboutToolStripButton.Text = "About"; this.AboutToolStripButton.Click += new System.EventHandler(this.AboutToolStripButton_Click); // + // NewVersionLabel + // + this.NewVersionLabel.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; + this.NewVersionLabel.BackColor = System.Drawing.Color.Transparent; + this.NewVersionLabel.ForeColor = System.Drawing.Color.Red; + this.NewVersionLabel.LinkColor = System.Drawing.Color.Red; + this.NewVersionLabel.IsLink = true; + this.NewVersionLabel.Visible = false; + this.NewVersionLabel.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline; + this.NewVersionLabel.Name = "NewVersionLabel"; + this.NewVersionLabel.Size = new System.Drawing.Size(26, 19); + this.NewVersionLabel.Text = "New version available"; + this.NewVersionLabel.Click += new System.EventHandler(this.NewVersionLabel_Click); + // // VersionLabel // this.VersionLabel.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; @@ -732,6 +767,7 @@ namespace Netch.Forms private System.Windows.Forms.SearchComboBox ModeComboBox; private System.Windows.Forms.Label ModeLabel; private System.Windows.Forms.ToolStripMenuItem ModeToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem HelpToolStripMenuItem; private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLabel; private System.Windows.Forms.NotifyIcon NotifyIcon; private System.Windows.Forms.ContextMenuStrip NotifyMenu; @@ -742,6 +778,7 @@ namespace Netch.Forms private System.Windows.Forms.TextBox ProfileNameText; private System.Windows.Forms.TableLayoutPanel ProfileTable; private System.Windows.Forms.ToolStripMenuItem reinstallTapDriverToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem CheckForUpdatesToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem ReloadModesToolStripMenuItem; private System.Windows.Forms.ComboBox ServerComboBox; private System.Windows.Forms.Label ServerLabel; @@ -760,11 +797,11 @@ namespace Netch.Forms private System.Windows.Forms.ToolStripMenuItem UpdateServersFromSubscribeLinksToolStripMenuItem; private System.Windows.Forms.ToolStripStatusLabel UploadSpeedLabel; private System.Windows.Forms.ToolStripStatusLabel UsedBandwidthLabel; + private System.Windows.Forms.ToolStripLabel NewVersionLabel; private System.Windows.Forms.ToolStripLabel VersionLabel; - - #endregion - private System.Windows.Forms.ToolStripStatusLabel NatTypeStatusLightLabel; private System.Windows.Forms.ToolStripStatusLabel blankToolStripStatusLabel; + + #endregion } } \ No newline at end of file diff --git a/Netch/Forms/MainForm.MenuStrip.cs b/Netch/Forms/MainForm.MenuStrip.cs index 11134623..c526abf3 100644 --- a/Netch/Forms/MainForm.MenuStrip.cs +++ b/Netch/Forms/MainForm.MenuStrip.cs @@ -224,6 +224,28 @@ namespace Netch.Forms #region 选项 + private void CheckForUpdatesToolStripMenuItem_Click(object sender, EventArgs e) + { + Task.Run(() => + { + void OnNewVersionNotFound(object o, EventArgs args) + { + _updater.NewVersionNotFound -= OnNewVersionNotFound; + NotifyTip(i18N.Translate("Already Latest version")); + } + + void OnNewVersionFoundFailed(object o, EventArgs args) + { + _updater.NewVersionFoundFailed -= OnNewVersionFoundFailed; + NotifyTip(i18N.Translate("New Version Found Failed"), info: false); + } + + _updater.NewVersionNotFound += OnNewVersionNotFound; + _updater.NewVersionFoundFailed += OnNewVersionFoundFailed; + CheckUpdate(); + }); + } + private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e) { Utils.Utils.Open(".\\"); diff --git a/Netch/Forms/MainForm.Misc.cs b/Netch/Forms/MainForm.Misc.cs index fc8e2fef..36bdff60 100644 --- a/Netch/Forms/MainForm.Misc.cs +++ b/Netch/Forms/MainForm.Misc.cs @@ -1,7 +1,14 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; using System.Threading.Tasks; +using System.Windows.Forms; using Netch.Controllers; +using Netch.Forms.Mode; using Netch.Utils; +using Process = System.Diagnostics.Process; namespace Netch.Forms { @@ -18,11 +25,62 @@ namespace Netch.Forms partial class MainForm { + private readonly UpdateChecker _updater = new UpdateChecker(); + private void CheckUpdate() { - var updater = new UpdateChecker(); - updater.NewVersionFound += (o, args) => { NotifyTip($"{i18N.Translate(@"New version available", ": ")}{updater.LatestVersionNumber}"); }; - updater.Check(false, Global.Settings.CheckBetaUpdate); + _updater.NewVersionFound += (o, args) => + { + if (_updater.LatestVersionDownloadUrl.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) + { + NotifyTip($"{i18N.Translate(@"New version available", ": ")}{_updater.LatestVersionNumber}"); + NewVersionLabel.Visible = true; + } + }; + _updater.Check(Global.Settings.CheckBetaUpdate); + } + + private async void NewVersionLabel_Click(object sender, EventArgs e) + { + if (MessageBoxX.Show("Download and install now?", confirm: true) != DialogResult.OK) + return; + NotifyTip("Start downloading new version"); + var fileName = $"Netch{_updater.LatestVersionNumber}.zip"; + var fileFullPath = Path.Combine(Global.NetchDir, "data", fileName); + if (File.Exists(fileFullPath)) + { + if (Utils.Utils.IsZipValid(fileFullPath)) + { + // if debugging process stopped, debugger will kill child processes!!!! + // 调试进程结束,调试器将会杀死子进程 + // uncomment if(!Debugger.isAttach) block in NetchUpdater Project's main() method and attach to NetchUpdater process to debug + // 在 NetchUpdater 项目的 main() 方法中取消注释 if(!Debugger.isAttach)块,并附加到 NetchUpdater 进程进行调试 + Process.Start(new ProcessStartInfo + { + FileName = Path.Combine(Global.NetchDir, "NetchUpdater.exe"), + Arguments = + $"{Global.Settings.UDPSocketPort} {fileFullPath} {Global.NetchDir}" + }); + return; + } + + File.Delete(fileFullPath); + } + + await WebUtil.DownloadFileAsync(WebUtil.CreateRequest(_updater.LatestVersionDownloadUrl), fileFullPath); + if (Utils.Utils.IsZipValid(fileFullPath)) + { + Process.Start(new ProcessStartInfo + { + FileName = "cmd", + Arguments = + $"/c {Path.Combine(Global.NetchDir, "NetchUpdater.exe")} {Global.Settings.UDPSocketPort} {fileFullPath} {Global.NetchDir}" + }); + } + else + { + NotifyTip("Download update failed"); + } } } } \ No newline at end of file diff --git a/Netch/Forms/MainForm.Status.cs b/Netch/Forms/MainForm.Status.cs index 86209e2e..49e5b1da 100644 --- a/Netch/Forms/MainForm.Status.cs +++ b/Netch/Forms/MainForm.Status.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.Threading; +using System.Windows; using Netch.Models; using Netch.Utils; diff --git a/Netch/Forms/MainForm.cs b/Netch/Forms/MainForm.cs index 45869b4b..9489b8d4 100644 --- a/Netch/Forms/MainForm.cs +++ b/Netch/Forms/MainForm.cs @@ -193,6 +193,7 @@ namespace Netch.Forms AddVMessServerToolStripMenuItem.Text = i18N.Translate("Add [VMess] Server"); AddTrojanServerToolStripMenuItem.Text = i18N.Translate("Add [Trojan] Server"); ModeToolStripMenuItem.Text = i18N.Translate("Mode"); + HelpToolStripMenuItem.Text = i18N.Translate("Help"); CreateProcessModeToolStripMenuItem.Text = i18N.Translate("Create Process Mode"); SubscribeToolStripMenuItem.Text = i18N.Translate("Subscribe"); ManageSubscribeLinksToolStripMenuItem.Text = i18N.Translate("Manage Subscribe Links"); @@ -204,8 +205,10 @@ namespace Netch.Forms UpdateACLToolStripMenuItem.Text = i18N.Translate("Update ACL"); updateACLWithProxyToolStripMenuItem.Text = i18N.Translate("Update ACL with proxy"); reinstallTapDriverToolStripMenuItem.Text = i18N.Translate("Reinstall TUN/TAP driver"); + CheckForUpdatesToolStripMenuItem.Text = i18N.Translate("Check for updates"); OpenDirectoryToolStripMenuItem.Text = i18N.Translate("Open Directory"); AboutToolStripButton.Text = i18N.Translate("About"); + NewVersionLabel.Text = i18N.Translate("New version available"); // VersionLabel.Text = i18N.Translate("xxx"); exitToolStripMenuItem.Text = i18N.Translate("Exit"); ConfigurationGroupBox.Text = i18N.Translate("Configuration"); diff --git a/Netch/Models/GitHubRelease/SuffixVersion.cs b/Netch/Models/GitHubRelease/SuffixVersion.cs index e52d0aa4..ecf201ef 100644 --- a/Netch/Models/GitHubRelease/SuffixVersion.cs +++ b/Netch/Models/GitHubRelease/SuffixVersion.cs @@ -128,5 +128,10 @@ namespace Netch.Models.GitHubRelease return hashCode; } } + + public override string ToString() + { + return $"{Major}.{Minor}.{Patch}{(string.IsNullOrEmpty(PreRelease) ? "" : "-")}{PreRelease}{(Build == 0 ? "" : Build.ToString())}"; + } } } \ No newline at end of file diff --git a/Netch/Netch.cs b/Netch/Netch.cs index e99b7395..984252e3 100644 --- a/Netch/Netch.cs +++ b/Netch/Netch.cs @@ -67,12 +67,14 @@ namespace Netch if (!mutex.WaitOne(0, false)) { OnlyInstance.Send(OnlyInstance.Commands.Show); + Logging.Info("唤起单实例"); // 退出进程 Environment.Exit(1); } Task.Run(OnlyInstance.Server); + Logging.Info("启动单实例"); // 绑定错误捕获 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); diff --git a/Netch/Netch.csproj b/Netch/Netch.csproj index 7416ff3b..1aaa67d0 100644 --- a/Netch/Netch.csproj +++ b/Netch/Netch.csproj @@ -68,9 +68,11 @@ + + diff --git a/Netch/Utils/Utils.cs b/Netch/Utils/Utils.cs index e84e2455..52a59ad6 100644 --- a/Netch/Utils/Utils.cs +++ b/Netch/Utils/Utils.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics; using System.IO; +using System.IO.Compression; using System.Linq; using System.Net; using System.Net.Sockets; @@ -103,5 +104,19 @@ namespace Netch.Utils return ""; } } + + public static bool IsZipValid(string path) + { + try + { + using var zipFile = ZipFile.OpenRead(path); + _ = zipFile.Entries; + return true; + } + catch (InvalidDataException) + { + return false; + } + } } } \ No newline at end of file diff --git a/Netch/Utils/WebUtil.cs b/Netch/Utils/WebUtil.cs index 3a589f10..827e5b9b 100644 --- a/Netch/Utils/WebUtil.cs +++ b/Netch/Utils/WebUtil.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Net; using System.Text; @@ -8,7 +9,8 @@ namespace Netch.Utils { public class WebUtil { - public const string DefaultUserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"; + public const string DefaultUserAgent = + @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"; private static int DefaultGetTimeout => Global.Settings.RequestTimeout; @@ -43,6 +45,24 @@ namespace Netch.Utils return content; } + /// + /// + /// + public static async Task> DownloadBytesAsync(HttpWebRequest req) + { + var content = new List(); + var buffer = new byte[1024]; + var response = (HttpWebResponse) await req.GetResponseAsync(); + using (var responseStream = response.GetResponseStream()) + { + await responseStream.ReadAsync(buffer, 0, buffer.Length); + content.AddRange(buffer); + } + + response.Close(); + return content; + } + /// /// /// @@ -67,10 +87,15 @@ namespace Netch.Utils /// public static async Task DownloadFileAsync(HttpWebRequest req, string fileFullPath) { - var dir = Path.GetDirectoryName(fileFullPath) ?? throw new ArgumentException(); - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - File.WriteAllText(fileFullPath, await DownloadStringAsync(req)); + using var webResponse = (HttpWebResponse) await req.GetResponseAsync(); + var fileStream = File.OpenWrite(fileFullPath); + using (var input = webResponse.GetResponseStream()) + { + await input.CopyToAsync(fileStream); + } + + fileStream.Flush(); + fileStream.Close(); } } } \ No newline at end of file diff --git a/NetchUpdater/.gitignore b/NetchUpdater/.gitignore new file mode 100644 index 00000000..0a079b63 --- /dev/null +++ b/NetchUpdater/.gitignore @@ -0,0 +1,2 @@ +/bin +/obj \ No newline at end of file diff --git a/NetchUpdater/NetchUpdater.csproj b/NetchUpdater/NetchUpdater.csproj new file mode 100644 index 00000000..b20a4b1d --- /dev/null +++ b/NetchUpdater/NetchUpdater.csproj @@ -0,0 +1,55 @@ + + + + + Debug + AnyCPU + {828318A8-9B90-4A5F-BD6B-E632CC9D8933} + Exe + Properties + NetchUpdater + NetchUpdater + v4.8 + 512 + + + pdbonly + true + TRACE + prompt + 4 + bin\x64\Release\ + x64 + + + true + full + false + DEBUG;TRACE + prompt + 4 + bin\x64\Debug\ + x64 + + + + + + + + + + + + + + + + + diff --git a/NetchUpdater/Program.cs b/NetchUpdater/Program.cs new file mode 100644 index 00000000..32760178 --- /dev/null +++ b/NetchUpdater/Program.cs @@ -0,0 +1,172 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +namespace NetchUpdater +{ + internal class Program + { + public static void Main(string[] args) + { + var updaterDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); + string zipFile, netchDir; + int port; + + try + { + if (args.Length != 3) + { + Console.WriteLine("The program is not user-oriented\n此程序不是面向用户的"); + return; + } + + try + { + var portParseResult = int.TryParse(args[0], out port); + if (!portParseResult) + { + Console.WriteLine("arg0 Port Parse failed"); + return; + } + } + catch (IndexOutOfRangeException) + { + Console.WriteLine("arg0 Port not specified"); + return; + } + + try + { + var zipFileParseResult = File.Exists(zipFile = Path.GetFullPath(args[1])); + if (!zipFileParseResult) + { + Console.WriteLine("arg1 Zip file Not found"); + return; + } + } + catch (IndexOutOfRangeException) + { + Console.Write("arg1 Zip file not specified"); + return; + } + + try + { + var netchDirParseResult = !File.Exists(Path.Combine(netchDir = Path.GetFullPath(args[2]), "Netch.exe")); + if (netchDirParseResult) + { + Console.Write("arg2 Netch Directory doesn't seems right"); + return; + } + } + catch (IndexOutOfRangeException) + { + Console.Write("arg2 Netch Directory not specified"); + return; + } + + if (File.Exists(Path.Combine(updaterDirectory, "Netch.exe"))) + { + var tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tempPath); + File.Copy(Process.GetCurrentProcess().MainModule.FileName, + Path.Combine(tempPath, AppDomain.CurrentDomain.FriendlyName)); + Process.Start(new ProcessStartInfo + { + FileName = Path.Combine(tempPath, AppDomain.CurrentDomain.FriendlyName), + Arguments = $"{args[0]} {args[1]} {args[2]}", + UseShellExecute = false + }); + + return; + } + + /*if (!Debugger.IsAttached) + { + Console.WriteLine("Waiting Attach"); + Thread.Sleep(1000); + }*/ + + Process[] _; + if ((_ = Process.GetProcessesByName("Netch")).Any()) + { + Console.WriteLine("Found Netch process, Send exit command"); + try + { + var udpClient = new UdpClient("127.0.0.1", port); + var sendBytes = Encoding.ASCII.GetBytes("Exit"); + udpClient.Send(sendBytes, sendBytes.Length); + } + catch + { + Console.WriteLine("Send command failed"); + return; + } + + + foreach (var proc in _) + { + try + { + proc.WaitForExit(); + } + catch (Exception) + { + // ignored + } + } + } + + Console.WriteLine("Extract Zip"); + ExtractToDirectory(zipFile, netchDir, true); + Console.WriteLine("Start Netch"); + Process.Start(new ProcessStartInfo + { + FileName = Path.Combine(netchDir, "Netch.exe"), + UseShellExecute = true, + }); + } + catch (Exception e) + { + if(e is InvalidDataException) + Console.WriteLine("Zip file Broken"); + Console.WriteLine(e.ToString()); + } + finally + { + Thread.Sleep(1000); + } + } + + public static void ExtractToDirectory(string archiveFileName, string destinationDirectoryName, bool overwrite) + { + if (!overwrite) + { + ZipFile.ExtractToDirectory(archiveFileName, destinationDirectoryName); + } + else + { + using (var archive = ZipFile.OpenRead(archiveFileName)) + { + foreach (var file in archive.Entries) + { + Console.WriteLine(file.FullName); + var completeFileName = Path.Combine(destinationDirectoryName, file.FullName); + var directory = Path.GetDirectoryName(completeFileName); + + if (!Directory.Exists(directory) && !string.IsNullOrEmpty(directory)) + Directory.CreateDirectory(directory); + + if (file.Name != "") + file.ExtractToFile(completeFileName, true); + } + } + } + } + } +} \ No newline at end of file diff --git a/NetchUpdater/Properties/AssemblyInfo.cs b/NetchUpdater/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..746c1612 --- /dev/null +++ b/NetchUpdater/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NetchUpdater")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NetchUpdater")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("828318A8-9B90-4A5F-BD6B-E632CC9D8933")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file