diff --git a/installer/Installer/Installer.csproj b/installer/Installer/Installer.csproj
index 4106cb0..4bf4764 100644
--- a/installer/Installer/Installer.csproj
+++ b/installer/Installer/Installer.csproj
@@ -7,4 +7,9 @@
true
+
+
+
+
+
diff --git a/installer/Installer/MainWindow.xaml.cs b/installer/Installer/MainWindow.xaml.cs
index a4cc502..9ae2784 100644
--- a/installer/Installer/MainWindow.xaml.cs
+++ b/installer/Installer/MainWindow.xaml.cs
@@ -12,6 +12,17 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
+using COSXML;
+using COSXML.Auth;
+using COSXML.Model.Object;
+using COSXML.Model.Bucket;
+using COSXML.CosException;
+using System.IO;
+using Newtonsoft.Json;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Text.Json.Nodes;
+using System.Diagnostics;
namespace Installer
{
@@ -26,3 +37,643 @@ namespace Installer
}
}
}
+
+namespace Downloader
+{
+ class Program
+ {
+ static List newFileName = new List(); //新文件名
+ static List updateFileName = new List(); //更新文件名
+ static string ProgramName = "THUAI6"; //要运行或下载的程序名称
+ static string playerFolder = "player"; //选手代码保存文件夹路径
+ static string startName = "maintest.exe"; //启动的程序名
+
+ public class Data
+ {
+ public static string path = ""; //标记路径记录文件THUAI6.dat的路径
+ public static string FilePath = ""; //最后一级为THUAI6文件夹所在目录
+ public static string dataPath = ""; //C盘的文档文件夹
+ public Data(string path)
+ {
+ //dataPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ dataPath= new DirectoryInfo(".").FullName;
+ Data.path=System.IO.Path.Combine(dataPath, "THUAI6.dat");
+ if (File.Exists(Data.path))
+ {
+ using (StreamReader r = new StreamReader(Data.path))
+ FilePath = r.ReadLine().Replace('\\', '/'); //读取THUAI6.dat文件的第一行
+ }
+ else
+ {
+ FilePath = System.IO.Path.GetDirectoryName(@path);
+
+ //将dat文件写入程序运行路径
+ FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
+ StreamWriter sw = new StreamWriter(fs);
+ sw.Write(path);
+ sw.Flush();
+ sw.Close();
+ }
+ }
+
+ public static void ChangeData(string newLine)
+ {
+ if (Directory.Exists(@newLine)) //判断文件夹是否存在
+ {
+ Console.Write($"是否创建新路径 {newLine}?y/n:");
+ if (Console.Read() != 'y')
+ {
+ Console.WriteLine("创建取消!"); return;
+ }
+
+ using (StreamWriter w = new StreamWriter(path))
+ w.WriteLine(@newLine.Trim('\r').Trim('\n'));
+ Console.WriteLine($"当前下载路径为{newLine}");
+ }
+ }
+
+ public static void ResetFilepath(string newPath)
+ {
+ FilePath=newPath.Replace('\\', '/');
+ path=System.IO.Path.Combine(dataPath, "THUAI6.dat");
+ FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
+ StreamWriter sw = new StreamWriter(fs);
+ fs.SetLength(0);
+ sw.Write(newPath);
+ sw.Flush();
+ sw.Close();
+ fs.Close();
+ }
+
+ }
+ public class Tencent_cos_download
+ {
+ public void download(string download_dir, string key)
+ {
+ //download_dir标记根文件夹路径,key为相对根文件夹的路径(不带./)
+ //初始化CosXmlConfig(提供配置SDK接口)
+ string appid = "1314234950"; //设置腾讯云账户的账户标识(APPID)
+ string region = "ap-beijing"; //设置一个默认的存储桶地域
+ CosXmlConfig config = new CosXmlConfig.Builder()
+ .IsHttps(true) //设置默认 HTTPS 请求
+ .SetAppid(appid) //设置腾讯云账户的账户标识 APPID
+ .SetRegion(region) //设置一个默认的存储桶地域
+ .SetDebugLog(true) //显示日志
+ .Build(); //创建 CosXmlConfig 对象
+
+ //永久密钥访问凭证
+ string secretId = "AKIDvhEVXN4cv0ugIlFYiniV6Wk1McfkplYA"; //"云 API 密钥 SecretId";
+ string secretKey = "YyGLGCJG4f5VsEUddnz9JSRPSSK8sYBo"; //"云 API 密钥 SecretKey";
+
+ long durationSecond = 1000; //每次请求签名有效时长,单位为秒
+ QCloudCredentialProvider cosCredentialProvider = new DefaultQCloudCredentialProvider(
+ secretId, secretKey, durationSecond);
+
+ //初始化 CosXmlServer
+ CosXmlServer cosXml = new CosXmlServer(config, cosCredentialProvider);
+
+ //创建存储桶
+ try
+ {
+ string bucket = "thuai6-1314234950"; //格式:BucketName-APPID
+ string localDir = System.IO.Path.GetDirectoryName(download_dir); //本地文件夹
+ string localFileName = System.IO.Path.GetFileName(download_dir); //指定本地保存的文件名
+ GetObjectRequest request = new GetObjectRequest(bucket, key, localDir, localFileName);
+
+ Dictionary test = request.GetRequestHeaders();
+ request.SetCosProgressCallback(delegate (long completed, long total)
+ {
+ Console.WriteLine(String.Format("progress = {0:##.##}%", completed * 100.0 / total));
+ });
+ //执行请求
+ GetObjectResult result = cosXml.GetObject(request);
+ //请求成功
+ }
+ catch (CosClientException clientEx)
+ {
+ throw clientEx;
+ }
+ catch (CosServerException serverEx)
+ {
+ throw serverEx;
+ }
+ }
+
+ public static void GetNewHash()
+ {
+ Tencent_cos_download Downloader = new Tencent_cos_download();
+ Downloader.download(System.IO.Path.Combine(Data.FilePath, "hash.json"), "hash.json");
+ }
+
+ public static string GetFileMd5Hash(string strFileFullPath)
+ {
+ FileStream fst = null;
+ try
+ {
+ fst=new FileStream(strFileFullPath, FileMode.Open);
+ byte[] data = MD5.Create().ComputeHash(fst);
+
+ StringBuilder sBuilder = new StringBuilder();
+
+ for (int i = 0; i < data.Length; i++)
+ {
+ sBuilder.Append(data[i].ToString("x2"));
+ }
+
+ fst.Close();
+ return sBuilder.ToString().ToLower();
+ }
+ catch (Exception)
+ {
+ if (fst != null)
+ fst.Close();
+ return "";
+ }
+ finally { }
+ }
+
+ private static void Check()
+ {
+ string json, MD5, jsonName;
+ int newFile = 0, updateFile = 0;
+ newFileName.Clear();
+ updateFileName.Clear();
+ jsonName = "hash.json";
+
+ Tencent_cos_download Downloader = new Tencent_cos_download();
+ try
+ {
+ //如果json存在就删了重新下
+ if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
+ {
+ File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
+ Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
+ }
+ else
+ {
+ Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
+ }
+ }
+ catch (CosClientException clientEx)
+ {
+ //请求失败
+ Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
+ return;
+ }
+ catch (CosServerException serverEx)
+ {
+ //请求失败
+ Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
+ return;
+ }
+
+ using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
+ json = r.ReadToEnd();
+ json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
+ Dictionary jsonDict = JsonConvert.DeserializeObject>(json);
+ foreach (KeyValuePair pair in jsonDict)
+ {
+ MD5=GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key));
+ if (MD5.Length == 0) //文档不存在
+ newFileName.Add(pair.Key);
+ else if (MD5 != pair.Value) //MD5不匹配
+ updateFileName.Add(pair.Key);
+ }
+
+ newFile = newFileName.Count;
+ updateFile = updateFileName.Count;
+ Console.WriteLine("----------------------" + Environment.NewLine);
+
+ if (newFile + updateFile == 0)
+ {
+ Console.WriteLine("当前平台已是最新版本!" + Environment.NewLine);
+ newFileName.Clear(); updateFileName.Clear();
+ }
+ else
+ {
+ Console.WriteLine($"发现{newFile}个新文件" + Environment.NewLine);
+ foreach (string filename in newFileName)
+ {
+ Console.WriteLine(filename);
+ }
+ Console.WriteLine(Environment.NewLine + $"发现{updateFile}个文件更新" + Environment.NewLine);
+ foreach (string filename in updateFileName)
+ {
+ Console.WriteLine(filename);
+ }
+ Console.Write(Environment.NewLine + "是否下载新文件? y/n:");
+ if (Console.Read() != 'y') Console.WriteLine("下载取消!");
+ else Download();
+ }
+ }
+ private static void Download()
+ {
+ Tencent_cos_download Downloader = new Tencent_cos_download();
+
+ int newFile = 0, updateFile = 0;
+ int totalnew = newFileName.Count, totalupdate = updateFileName.Count;
+
+ if (newFileName.Count > 0 || updateFileName.Count > 0)
+ {
+ try
+ {
+ foreach (string filename in newFileName)
+ {
+ Console.WriteLine(newFile + 1 + "/" + totalnew + ":开始下载" + filename);
+ Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename);
+ Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
+ newFile++;
+ }
+ foreach (string filename in updateFileName)
+ {
+ Console.WriteLine(updateFile + 1 + "/" + totalupdate + ":开始下载" + filename);
+ File.Delete(System.IO.Path.Combine(@Data.FilePath, filename));
+ Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename);
+ Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
+ updateFile++;
+ }
+ }
+ catch (CosClientException clientEx)
+ {
+ //请求失败
+ Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
+ return;
+ }
+ catch (CosServerException serverEx)
+ {
+ //请求失败
+ Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
+ return;
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+ else Console.WriteLine("当前平台已是最新版本!" + Environment.NewLine);
+ newFileName.Clear();
+ updateFileName.Clear();
+ }
+
+ public static bool CheckAlreadyDownload() //检查是否已经下载
+ {
+ string existpath = System.IO.Path.Combine(Data.dataPath, "Exists.txt");
+ if (!File.Exists(existpath)) //文件不存在
+ {
+ FileStream fs = new FileStream(existpath, FileMode.Create, FileAccess.ReadWrite);
+ fs.Close();
+ return false;
+ }
+ else //文件存在
+ {
+ FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.Read);
+ StreamReader sr = new StreamReader(fs);
+ if ("true"==sr.ReadLine())
+ {
+ sr.Close();
+ fs.Close();
+ return true;
+ }
+ else
+ {
+ sr.Close();
+ fs.Close();
+ return false;
+ }
+ }
+ }
+
+ public static void DownloadAll() //下载全部文件
+ {
+ string jsonName = "hash.json";
+ string json;
+ Tencent_cos_download Downloader = new Tencent_cos_download();
+
+ try
+ {
+ //如果json存在就删了重新下
+ if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
+ {
+ File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
+ Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
+ }
+ else
+ {
+ Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
+ }
+ }
+ catch (CosClientException clientEx)
+ {
+ //请求失败
+ Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
+ return;
+ }
+ catch (CosServerException serverEx)
+ {
+ //请求失败
+ Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
+ return;
+ }
+ using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
+ json = r.ReadToEnd();
+ json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
+ Dictionary jsonDict = JsonConvert.DeserializeObject>(json);
+
+ newFileName.Clear();
+ updateFileName.Clear();
+ foreach (KeyValuePair pair in jsonDict)
+ {
+ newFileName.Add(pair.Key);
+ }
+ Download();
+
+ string existpath = System.IO.Path.Combine(Data.dataPath, "Exists.txt");
+ FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
+ StreamWriter sw = new StreamWriter(fs);
+ fs.SetLength(0);
+ sw.Write("true");
+ sw.Close();
+ fs.Close();
+ }
+
+ public static void Change_all_hash(string topDir, Dictionary jsonDict) //更改HASH
+ {
+ DirectoryInfo theFolder = new DirectoryInfo(@topDir);
+ bool ifexist = false;
+
+ //遍历文件
+ foreach (FileInfo NextFile in theFolder.GetFiles())
+ {
+ string filepath = topDir+@"/"+NextFile.Name;//文件路径
+ Console.WriteLine(filepath);
+ foreach (KeyValuePair pair in jsonDict)
+ {
+ if (System.IO.Path.Equals(filepath, System.IO.Path.Combine(Data.FilePath, pair.Key).Replace('\\', '/')))
+ {
+ ifexist = true;
+ string MD5 = GetFileMd5Hash(filepath);
+ jsonDict[pair.Key] = MD5;
+ }
+ }
+ if (!ifexist && NextFile.Name!="hash.json")
+ {
+ string MD5 = GetFileMd5Hash(filepath);
+ string relapath = filepath.Replace(Data.FilePath+'/', string.Empty);
+ jsonDict.Add(relapath, MD5);
+ }
+ ifexist = false;
+ }
+
+ //遍历文件夹
+ foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
+ {
+ if (System.IO.Path.Equals(NextFolder.FullName,
+ System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder))))
+ {
+ foreach (FileInfo NextFile in NextFolder.GetFiles())
+ {
+ if (NextFile.Name=="README.md")
+ {
+ string MD5 = GetFileMd5Hash(NextFile.FullName);
+ string relapath = NextFile.FullName.Replace('\\', '/').Replace(Data.FilePath+'/', string.Empty);
+ jsonDict.Add(relapath, MD5);
+ }
+ }
+ continue; //如果是选手文件夹就忽略
+ }
+ Change_all_hash(NextFolder.FullName.Replace('\\', '/'), jsonDict);
+ }
+ }
+ public static void UpdateHash()
+ {
+ while (true)
+ {
+ if (Directory.Exists(Data.FilePath))
+ {
+ string json;
+ if (!File.Exists(System.IO.Path.Combine(Data.FilePath, "hash.json")))
+ {
+ Console.WriteLine("hash.json文件丢失!即将重新下载该文件!");
+ GetNewHash();
+ }
+ using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, "hash.json")))
+ json = r.ReadToEnd();
+ json = json.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("/", @"\\");
+ Dictionary jsonDict = JsonConvert.DeserializeObject>(json);
+ Change_all_hash(Data.FilePath, jsonDict);
+ OverwriteHash(jsonDict);
+ break;
+ }
+ else
+ {
+ Console.WriteLine("读取路径失败!请重新输入文件路径:");
+ Data.ResetFilepath(Console.ReadLine());
+ }
+ }
+ }
+
+ public static void DeleteAll()
+ {
+ DirectoryInfo di = new DirectoryInfo(Data.FilePath);
+ DirectoryInfo player = new DirectoryInfo(System.IO.
+ Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder)));
+ try
+ {
+ foreach (FileInfo file in di.GetFiles())
+ {
+ file.Delete();
+ }
+ foreach (FileInfo file in player.GetFiles())
+ {
+ if (file.Name=="README.md")
+ {
+ continue;
+ }
+ string filename = System.IO.Path.GetFileName(file.FullName);
+ file.MoveTo(System.IO.Path.Combine(Data.FilePath, filename));
+ }
+ foreach (DirectoryInfo subdi in di.GetDirectories())
+ {
+ subdi.Delete(true);
+ }
+ }
+ catch (UnauthorizedAccessException)
+ {
+ Console.WriteLine("权限不足,无法删除!");
+ return;
+ }
+ catch (DirectoryNotFoundException)
+ {
+ Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
+ return;
+ }
+ catch (IOException)
+ {
+ Console.WriteLine("文件已经打开,请关闭后再删除");
+ return;
+ }
+
+ string existpath = System.IO.Path.Combine(Data.dataPath, "Exists.txt");
+ FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
+ StreamWriter sw = new StreamWriter(fs);
+ fs.SetLength(0);
+ sw.Write("false");
+ sw.Close();
+ fs.Close();
+
+ try
+ {
+ File.Delete(Data.path);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ Console.WriteLine("权限不足,无法删除!");
+ return;
+ }
+ catch (DirectoryNotFoundException)
+ {
+ Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
+ return;
+ }
+ catch (IOException)
+ {
+ Console.WriteLine("文件已经打开,请关闭后再删除");
+ return;
+ }
+ Console.WriteLine($"删除成功!player文件夹中的文件已经放在{ProgramName}的根目录下");
+ }
+
+ public static void OverwriteHash(Dictionary jsonDict)
+ {
+ string Contentjson = JsonConvert.SerializeObject(jsonDict);
+ Contentjson=Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/");
+ File.WriteAllText(@System.IO.Path.Combine(Data.FilePath, "hash.json"), Contentjson);
+ }
+
+ public static void MoveProgram()
+ {
+ string newPath = Console.ReadLine();
+ DirectoryInfo newdi = new DirectoryInfo(newPath);
+ DirectoryInfo olddi = new DirectoryInfo(Data.FilePath);
+ try
+ {
+ foreach (DirectoryInfo direct in olddi.GetDirectories())
+ {
+ direct.MoveTo(System.IO.Path.Combine(newPath, direct.Name));
+ }
+ foreach (FileInfo file in olddi.GetFiles())
+ {
+ file.MoveTo(System.IO.Path.Combine(newPath, file.Name));
+ }
+ }
+ catch (DirectoryNotFoundException)
+ {
+ Console.WriteLine("原路径未找到!请检查文件是否损坏");
+ foreach (DirectoryInfo newdirect in newdi.GetDirectories())
+ {
+ newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath, newdirect.Name));
+ }
+ foreach (FileInfo file in newdi.GetFiles())
+ {
+ file.MoveTo(System.IO.Path.Combine(Data.FilePath, file.Name));
+ }
+ Console.WriteLine("移动失败!");
+ }
+ catch (IOException)
+ {
+ Console.WriteLine("文件已打开或者目标路径下有同名文件!");
+ foreach (DirectoryInfo newdirect in newdi.GetDirectories())
+ {
+ newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath, newdirect.Name));
+ }
+ foreach (FileInfo file in newdi.GetFiles())
+ {
+ file.MoveTo(System.IO.Path.Combine(Data.FilePath, file.Name));
+ }
+ Console.WriteLine("移动失败!");
+ }
+ Data.ResetFilepath(newPath);
+ Console.WriteLine("更改路径成功!");
+ }
+ public static void main(string[] args)
+ {
+ Data date = new Data("");
+ while (true)
+ {
+ Console.WriteLine($"1. 更新hash.json 2. 检查更新 3.下载{ProgramName} 4.删除{ProgramName} 5.启动进程 6.移动{ProgramName}到其它路径");
+ string choose = Console.ReadLine();
+ if (choose=="1")
+ {
+ if (!CheckAlreadyDownload())
+ {
+ Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
+ continue;
+ }
+ UpdateHash();
+ }
+ else if (choose=="2")
+ {
+ if (!CheckAlreadyDownload())
+ {
+ Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
+ continue;
+ }
+ while (true)
+ {
+ if (Data.FilePath!=null && Directory.Exists(Data.FilePath))
+ {
+ Check();
+ break;
+ }
+ else
+ {
+ Console.WriteLine("读取路径失败!请重新输入文件路径:");
+ Data.ResetFilepath(Console.ReadLine());
+ }
+ }
+ }
+ else if (choose =="3")
+ {
+ if (CheckAlreadyDownload())
+ {
+ Console.WriteLine($"已经将{ProgramName}下载到{Data.FilePath}!若要重新下载请先完成删除操作!");
+
+ }
+ else
+ {
+ string newpath;
+ Console.WriteLine("请输入下载路径:");
+ newpath=Console.ReadLine();
+ Data.ResetFilepath(newpath);
+ DownloadAll();
+ }
+ }
+ else if (choose=="4")
+ {
+ DeleteAll();
+ }
+ else if (choose=="5")
+ {
+ if (CheckAlreadyDownload())
+ {
+ Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
+ }
+ else
+ {
+ Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
+ }
+ }
+ else if (choose=="6")
+ {
+ MoveProgram();
+ }
+ else if (choose=="exit")
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+