diff --git a/installer/Installer/Installer.csproj b/installer/Installer/Installer.csproj
index 53d5639..e63a124 100644
--- a/installer/Installer/Installer.csproj
+++ b/installer/Installer/Installer.csproj
@@ -6,9 +6,11 @@
enable
true
true
+ dotNetRuntime
+
diff --git a/installer/Installer/MainWindow.xaml b/installer/Installer/MainWindow.xaml
index 4e74b10..bf58112 100644
--- a/installer/Installer/MainWindow.xaml
+++ b/installer/Installer/MainWindow.xaml
@@ -49,7 +49,7 @@
-
+
diff --git a/installer/Installer/Model.cs b/installer/Installer/Model.cs
index 6799896..d78f9be 100644
--- a/installer/Installer/Model.cs
+++ b/installer/Installer/Model.cs
@@ -33,6 +33,8 @@ using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.GZip;
using static System.Net.WebRequestMethods;
using File = System.IO.File;
+using System.Linq;
+using Installer;
namespace starter.viewmodel.settings
{
@@ -318,6 +320,15 @@ namespace Downloader
{
static List newFileName = new List(); // 新文件名
static List updateFileName = new List(); // 更新文件名
+ static List updateFailed = new List(); //更新失败的文件名
+ static public List UpdateFailed
+ {
+ get { return updateFailed; }
+ }
+ static public void ResetUpdateFailedInfo()
+ {
+ updateFailed.Clear();
+ }
public static string ProgramName = "THUAI6"; // 要运行或下载的程序名称
public static string playerFolder = "player"; // 选手代码保存文件夹路径
public static string startName = "maintest.exe"; // 启动的程序名
@@ -495,7 +506,7 @@ namespace Downloader
FileStream fst = null;
try
{
- fst = new FileStream(strFileFullPath, FileMode.Open);
+ fst = new FileStream(strFileFullPath, FileMode.Open, FileAccess.Read);
byte[] data = MD5.Create().ComputeHash(fst);
StringBuilder sBuilder = new StringBuilder();
@@ -571,7 +582,19 @@ namespace Downloader
if (MD5.Length == 0) // 文档不存在
newFileName.Add(pair.Key);
else if (MD5.Equals("conflict"))
- MessageBox.Show($"文件{pair.Key}已打开,无法检查是否为最新,若需要,请关闭文件稍后手动检查更新", "文件正在使用", MessageBoxButton.OK, MessageBoxImage.Warning);
+ {
+ if (pair.Key.Equals("THUAI6/win/CAPI/cpp/.vs/CAPI/v17/Browse.VC.db"))
+ {
+ MessageBox.Show($"visual studio未关闭:\n" +
+ $"对于visual studio 2022,可以更新,更新会覆盖visual studio中已经打开的选手包;\n" +
+ $"若使用其他版本的visual studio是继续更新出现问题,请汇报;\n" +
+ $"若您自行修改了选手包,请注意备份;\n" +
+ $"若关闭visual studio后仍弹出,请汇报。\n\n",
+ "visual studio未关闭", MessageBoxButton.OK, MessageBoxImage.Information);
+ }
+ else
+ MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
else if (MD5 != pair.Value && System.IO.Path.GetFileName(pair.Key) != "AI.cpp" && System.IO.Path.GetFileName(pair.Key) != "AI.py") // MD5不匹配
updateFileName.Add(pair.Key);
}
@@ -622,19 +645,20 @@ namespace Downloader
if (UpdatePlanned)
{
Download();
- UpdatePlanned = false;
- return true;
+ if (updateFailed.Count == 0)
+ return true;
+ else
+ Check();
}
return false;
}
-
private static void Download()
{
Tencent_cos_download Downloader = new Tencent_cos_download();
int newFile = 0, updateFile = 0;
int totalnew = newFileName.Count, totalupdate = updateFileName.Count;
filenum = totalnew + totalupdate;
-
+ updateFailed.Clear();
if (newFileName.Count > 0 || updateFileName.Count > 0)
{
try
@@ -649,12 +673,20 @@ namespace Downloader
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);
+ try
+ {
+ File.Delete(System.IO.Path.Combine(@Data.FilePath, filename));
+ Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename);
+ }
+ catch (System.IO.IOException)
+ {
+ updateFailed = updateFailed.Append(filename).ToList();
+ }
//Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
updateFile++;
}
- UpdatePlanned = false;
+ if (updateFailed.Count == 0)
+ UpdatePlanned = false;
}
catch (CosClientException clientEx)
{
@@ -1160,6 +1192,50 @@ namespace Downloader
}
}
}
+
+ public static int CheckSelfVersion()
+ {
+ Tencent_cos_download downloader = new Tencent_cos_download();
+ string hashName = "installerHash.json";
+ string dir = Directory.GetCurrentDirectory();
+ try
+ {
+ if (File.Exists(System.IO.Path.Combine(dir, hashName)))
+ File.Delete(System.IO.Path.Combine(dir, hashName));
+ downloader.download(System.IO.Path.Combine(dir, hashName), hashName);
+ }
+ catch
+ {
+ return -1;
+ }
+ string json;
+ using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, hashName)))
+ json = r.ReadToEnd();
+ json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
+ Dictionary jsonDict = JsonConvert.DeserializeObject>(json);
+ if (jsonDict != null)
+ {
+ if (jsonDict.ContainsKey("InstallerUpdater.exe"))
+ {
+ string updaterHash = GetFileMd5Hash(System.IO.Path.Combine(dir, "InstallerUpdater.exe"));
+ if (updaterHash != null && !jsonDict["InstallerUpdater.exe"].Equals(updaterHash))
+ downloader.download(System.IO.Path.Combine(dir, "InstallerUpdater.exe"), "InstallerUpdater.exe");
+ }
+ else
+ return -1;
+ if (jsonDict.ContainsKey("Installer.exe"))
+ {
+ string selfHash = GetFileMd5Hash(System.IO.Path.Combine(dir, "Installer.exe"));
+ if (selfHash != null && !jsonDict["Installer.exe"].Equals(selfHash))
+ return 1;
+ }
+ else
+ return -1;
+ }
+ else
+ return -1;
+ return 0;
+ }
}
}
}
diff --git a/installer/Installer/ViewModel.cs b/installer/Installer/ViewModel.cs
index bc01e2a..b7b5b21 100644
--- a/installer/Installer/ViewModel.cs
+++ b/installer/Installer/ViewModel.cs
@@ -13,6 +13,7 @@ using Installer;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.IO;
using System.Windows.Automation.Provider;
+using System.Diagnostics;
namespace starter.viewmodel.settings
{
@@ -34,6 +35,22 @@ namespace starter.viewmodel.settings
//Program.Tencent_cos_download.UpdateHash();
+ Status = SettingsModel.Status.working;
+
+ switch (Program.Tencent_cos_download.CheckSelfVersion())
+ {
+ case 1:
+ if (MessageBoxResult.Yes == MessageBox.Show("下载器需要更新,是否现在更新", "需要更新", MessageBoxButton.YesNo))
+ {
+ Process.Start(Path.Combine(Directory.GetCurrentDirectory(), "InstallerUpdater.exe"));
+ Environment.Exit(0);
+ }
+ break;
+ case -1:
+ MessageBox.Show("下载器更新检查出错,将继续启动现有下载器");
+ break;
+ }
+
//实例化BackgroundWorker
asyncDownloader = new BackgroundWorker();
asyncUpdater = new BackgroundWorker();
@@ -113,6 +130,20 @@ namespace starter.viewmodel.settings
this.RaisePropertyChanged("LaunchBtnCont");
this.RaisePropertyChanged("UpdateInfo");
}
+ else
+ {
+ string updateFailList = "";
+ foreach (var Filename in Program.UpdateFailed)
+ {
+ updateFailList += Filename + "\n";
+ }
+ MessageBox.Show($"以下文件因被占用而未能成功更新:\n{updateFailList}请关闭它们,并再试一次");
+ Program.ResetUpdateFailedInfo();
+ Status = SettingsModel.Status.successful;
+ this.RaisePropertyChanged("UpdateBtnCont");
+ this.RaisePropertyChanged("UpdateInfo");
+ this.RaisePropertyChanged("LaunchBtnCont");
+ }
}
}
@@ -649,8 +680,8 @@ namespace starter.viewmodel.settings
{
UpdateInfoVis = Visibility.Visible;
this.RaisePropertyChanged("UpdateInfoVis");
- Status = SettingsModel.Status.working;
- this.RaisePropertyChanged("ProgressVis");
+ //Status = SettingsModel.Status.working;
+ //this.RaisePropertyChanged("ProgressVis");
Status = obj.checkUpdate();
this.RaisePropertyChanged("UpdateBtnCont");
this.RaisePropertyChanged("UpdateInfo");
diff --git a/installer/InstallerUpdater/App.xaml b/installer/InstallerUpdater/App.xaml
new file mode 100644
index 0000000..6d79e58
--- /dev/null
+++ b/installer/InstallerUpdater/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/installer/InstallerUpdater/App.xaml.cs b/installer/InstallerUpdater/App.xaml.cs
new file mode 100644
index 0000000..1d0153c
--- /dev/null
+++ b/installer/InstallerUpdater/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace InstallerUpdater
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/installer/InstallerUpdater/AssemblyInfo.cs b/installer/InstallerUpdater/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/installer/InstallerUpdater/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/installer/InstallerUpdater/InstallerUpdater.csproj b/installer/InstallerUpdater/InstallerUpdater.csproj
new file mode 100644
index 0000000..79fbb62
--- /dev/null
+++ b/installer/InstallerUpdater/InstallerUpdater.csproj
@@ -0,0 +1,19 @@
+
+
+
+ WinExe
+ net6.0-windows
+ enable
+ true
+ dotNetRuntime
+
+
+
+
+
+
+ true
+
+
+
+
diff --git a/installer/InstallerUpdater/MainWindow.xaml b/installer/InstallerUpdater/MainWindow.xaml
new file mode 100644
index 0000000..271161a
--- /dev/null
+++ b/installer/InstallerUpdater/MainWindow.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 正在尝试更新下载器
+
+
+
diff --git a/installer/InstallerUpdater/MainWindow.xaml.cs b/installer/InstallerUpdater/MainWindow.xaml.cs
new file mode 100644
index 0000000..1e61b9f
--- /dev/null
+++ b/installer/InstallerUpdater/MainWindow.xaml.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Program;
+using System.Diagnostics;
+using System.IO;
+using System.ComponentModel;
+
+namespace InstallerUpdater
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ BackgroundWorker asyncDownloader = new BackgroundWorker();
+ public MainWindow()
+ {
+ InitializeComponent();
+ asyncDownloader.DoWork += AsyncDownloader_DoWork;
+ asyncDownloader.RunWorkerCompleted += AsyncDownloader_RunWorkerCompleted;
+ if (asyncDownloader.IsBusy)
+ {
+ MessageBox.Show("更新失败,请汇报");
+ Process.Start(System.IO.Path.Combine(Updater.Dir, "Installer.exe"));
+ Application.Current.Shutdown();
+ }
+ else
+ asyncDownloader.RunWorkerAsync();
+ }
+
+ private void AsyncDownloader_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e)
+ {
+ if (e.Result == null)
+ {
+ MessageBox.Show("更新失败,请汇报");
+ }
+ else if ((bool)e.Result)
+ {
+ MessageBox.Show("已成功更新下载器,即将启动下载器");
+ }
+ else
+ {
+ MessageBox.Show("更新失败,请汇报");
+ }
+ Process.Start(System.IO.Path.Combine(Updater.Dir, "Installer.exe"));
+ Application.Current.Shutdown();
+ }
+
+ private void AsyncDownloader_DoWork(object? sender, DoWorkEventArgs e)
+ {
+ if (asyncDownloader.CancellationPending)
+ {
+ e.Cancel = true;
+ return;
+ }
+ else
+ {
+ if (Updater.UpdateInstaller())
+ e.Result = true;
+ else
+ e.Result = false;
+ }
+ }
+ }
+}
diff --git a/installer/InstallerUpdater/Program.cs b/installer/InstallerUpdater/Program.cs
new file mode 100644
index 0000000..b274a39
--- /dev/null
+++ b/installer/InstallerUpdater/Program.cs
@@ -0,0 +1,89 @@
+using COSXML.Auth;
+using COSXML.CosException;
+using COSXML.Model.Object;
+using COSXML;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Text;
+using Newtonsoft.Json;
+using System.Windows.Markup;
+using System;
+using System.Security.Cryptography;
+using System.Diagnostics;
+
+namespace Program
+{
+ class Updater
+ {
+ public static string Dir = Directory.GetCurrentDirectory();
+ public static string InstallerName = "Installer.exe";
+ public static string jsonKey = "installerHash.json";
+
+ public static bool UpdateInstaller()
+ {
+ try
+ {
+ download(Path.Combine(Dir, "newInstaller.exe"), InstallerName);
+ File.Delete(Path.Combine(Dir, InstallerName));
+ File.Move(Path.Combine(Dir, "newInstaller.exe"), Path.Combine(Dir, InstallerName));
+ }
+ catch
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public static 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 = "***"; //"云 API 密钥 SecretId";
+ string secretKey = "***"; //"云 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;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/installer.sln b/installer/installer.sln
index 5ad8dd7..d38e1a4 100644
--- a/installer/installer.sln
+++ b/installer/installer.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Installer", "Installer\Installer.csproj", "{C10AF177-0883-4D9D-B2DC-3516BE04DF81}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstallerUpdater", "InstallerUpdater\InstallerUpdater.csproj", "{B2E61AB9-F7BF-4C48-ABFC-60F7F214BB14}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{C10AF177-0883-4D9D-B2DC-3516BE04DF81}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C10AF177-0883-4D9D-B2DC-3516BE04DF81}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C10AF177-0883-4D9D-B2DC-3516BE04DF81}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B2E61AB9-F7BF-4C48-ABFC-60F7F214BB14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B2E61AB9-F7BF-4C48-ABFC-60F7F214BB14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B2E61AB9-F7BF-4C48-ABFC-60F7F214BB14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B2E61AB9-F7BF-4C48-ABFC-60F7F214BB14}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE