Files
netch/NetchUpdater/Program.cs
2020-08-26 14:05:08 +08:00

289 lines
9.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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
{
#region Check Arguments
if (CurrentProcess.MainModule == null)
{
Console.WriteLine("Current Process MainModule is null");
return;
}
if (args.Length != 3)
{
Console.WriteLine("The program is not user-oriented\n此程序不是面向用户的");
return;
}
// arg0 port
if (!int.TryParse(args[0], out var port))
{
Console.WriteLine("arg0 Port Parse failed");
return;
}
var updateExtracted = true;
// arg1 update File/Directory
var updatePath = Path.GetFullPath(args[1]);
if (File.Exists(updatePath))
{
updateExtracted = false;
}
else if (!Directory.Exists(updatePath))
{
Console.WriteLine("arg1 update file/directory Not found");
return;
}
// arg2 target Directory
string targetPath;
if (!File.Exists(Path.Combine(targetPath = Path.GetFullPath(args[2]), "Netch.exe")))
{
Console.Write("arg2 Netch Directory doesn't seems right");
return;
}
#region if under target Directory,then rerun in temp directory
if (UpdaterDirectory.StartsWith(targetPath))
{
// Updater 在目标目录下
// 将程序复制到临时目录,传递参数
var tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
var newUpdaterPath = Path.Combine(tempPath, UpdaterFriendlyName);
Directory.CreateDirectory(tempPath);
File.Copy(UpdaterFullName, newUpdaterPath);
Process.Start(new ProcessStartInfo
{
FileName = newUpdaterPath,
Arguments = $"{port} {updatePath} {targetPath}",
WorkingDirectory = tempPath,
UseShellExecute = false
});
result = true;
return;
}
#endregion
#endregion
/*while (!Debugger.IsAttached)
{
Console.WriteLine("Waiting Attach");
Thread.Sleep(1000);
}*/
#region Send Netch Exit command
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
}
}
}
#endregion
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
Console.WriteLine("Start Netch");
Process.Start(new ProcessStartInfo
{
FileName = Path.Combine(targetPath, "Netch.exe"),
UseShellExecute = true,
});
#endregion
result = true;
}
catch (Exception e)
{
if (e is InvalidDataException)
Console.WriteLine("Archive file Broken");
Console.WriteLine(e.ToString());
}
finally
{
if (!result)
{
Console.WriteLine("Press any key to exit...");
Console.Read();
}
}
}
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)
{
Directory.Move(sourceDirName, destDirName);
}
else
{
var DirStack = new Stack<string>();
DirStack.Push(sourceDirName);
while (DirStack.Count > 0)
{
var DirInfo = new DirectoryInfo(DirStack.Pop());
try
{
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}");
}
DirStack.Push(DirChildInfo.FullName);
}
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;
}
}
}
}