196 lines
6.6 KiB
C#
196 lines
6.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Deployment.Application;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using Newtonsoft.Json;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.Net.Http;
|
|
|
|
namespace ProgramLauncher
|
|
{
|
|
public partial class Form1 : Form
|
|
{
|
|
static string downloadServerUrl = "http://xr.flexing.ai:3030/XR_Server";
|
|
static string downloadFolderName = "Build";
|
|
static string jsonFileName = "file_list.json";
|
|
static string localVersionID = "versionID.txt";
|
|
|
|
static readonly HttpClient httpClient = new HttpClient();
|
|
|
|
public Form1()
|
|
{
|
|
downloadServerUrl = CombineUrl(downloadServerUrl, Program.projectName);
|
|
InitializeComponent();
|
|
}
|
|
|
|
private async void Form1_Load(object sender, EventArgs e)
|
|
{
|
|
Label_UpdateFileName.Text = string.Empty;
|
|
|
|
await CheckUpdate();
|
|
}
|
|
|
|
private async Task CheckUpdate()
|
|
{
|
|
var serverFileList = await GetServerFileList(downloadServerUrl);
|
|
if (serverFileList == null) return;
|
|
|
|
string latestVersionID = serverFileList.VersionID;
|
|
string localVersionID = GetLocalVersion();
|
|
|
|
if (latestVersionID != localVersionID)
|
|
{
|
|
Label_ProgressState.Text = "업데이트 중...";
|
|
|
|
foreach (var file in serverFileList.Files)
|
|
{
|
|
string localFilePath = Path.Combine(downloadFolderName, file.Key);
|
|
string serverHash = file.Value;
|
|
|
|
if (!File.Exists(localFilePath) || GetFileHash(localFilePath) != serverHash)
|
|
{
|
|
Label_UpdateFileName.Text = localFilePath;
|
|
string downloadFolder = CombineUrl(downloadServerUrl, downloadFolderName);
|
|
await DownloadFile(Path.Combine(downloadFolder, file.Key), localFilePath);
|
|
}
|
|
}
|
|
|
|
var serverFilePaths = new HashSet<string>(
|
|
serverFileList.Files.Keys.Select(file => file.Replace('\\', '/')) // 서버의 파일 경로를 통일
|
|
);
|
|
|
|
foreach (string localFile in Directory.GetFiles(downloadFolderName, "*", SearchOption.AllDirectories))
|
|
{
|
|
// 현재 파일의 상대 경로를 구함 (localFolder 기준)
|
|
string relativePath = localFile.Substring(downloadFolderName.Length + 1).Replace('\\', '/');
|
|
|
|
if (!serverFilePaths.Contains(relativePath))
|
|
{
|
|
File.Delete(localFile);
|
|
}
|
|
}
|
|
|
|
SaveLocalVersion(latestVersionID);
|
|
}
|
|
|
|
StartExecutableFile(downloadFolderName);
|
|
this.Close();
|
|
}
|
|
|
|
static async Task<ServerFileList> GetServerFileList(string serverUrl)
|
|
{
|
|
using (WebClient client = new WebClient())
|
|
{
|
|
try
|
|
{
|
|
string serverJsonUrl = CombineUrl(serverUrl, jsonFileName);
|
|
string json = await client.DownloadStringTaskAsync(serverJsonUrl);
|
|
return JsonConvert.DeserializeObject<ServerFileList>(json);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
static string GetLocalVersion()
|
|
{
|
|
return File.Exists(localVersionID) ? File.ReadAllText(localVersionID).Trim() : "";
|
|
}
|
|
static void SaveLocalVersion(string version)
|
|
{
|
|
File.WriteAllText(localVersionID, version);
|
|
}
|
|
|
|
static string GetFileHash(string filePath)
|
|
{
|
|
using (var sha256 = SHA256.Create())
|
|
using (var stream = File.OpenRead(filePath))
|
|
{
|
|
byte[] hash = sha256.ComputeHash(stream);
|
|
return BitConverter.ToString(hash).Replace("-", "").ToLower();
|
|
}
|
|
}
|
|
/*
|
|
static async Task DownloadFile(string url, string outputPath)
|
|
{
|
|
try
|
|
{
|
|
using (WebClient client = new WebClient())
|
|
{
|
|
Directory.CreateDirectory(Path.GetDirectoryName(outputPath) ?? "");
|
|
await client.DownloadFileTaskAsync(new Uri(url), outputPath);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
*/
|
|
static async Task DownloadFile(string url, string outputPath)
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(Path.GetDirectoryName(outputPath) ?? "");
|
|
|
|
using (var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
|
|
{
|
|
response.EnsureSuccessStatusCode(); // 200 OK가 아닐 경우 예외 발생
|
|
|
|
using (var stream = await response.Content.ReadAsStreamAsync())
|
|
using (var fileStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
|
{
|
|
await stream.CopyToAsync(fileStream);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
static void StartExecutableFile(string executeFolder)
|
|
{
|
|
string[] exeFiles = Directory.GetFiles(executeFolder, "*.exe", SearchOption.TopDirectoryOnly);
|
|
|
|
if (exeFiles.Length == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string executeFilePath = exeFiles.FirstOrDefault(file => !file.EndsWith("UnityCrashHandler64.exe", StringComparison.OrdinalIgnoreCase));
|
|
string executeFileName = Path.GetFileName(executeFilePath);
|
|
|
|
Process process = new Process();
|
|
process.StartInfo.UseShellExecute = true;
|
|
process.StartInfo.WorkingDirectory = executeFolder;
|
|
process.StartInfo.FileName = executeFileName;
|
|
process.Start();
|
|
}
|
|
|
|
static string CombineUrl(string baseUrl, string relativePath)
|
|
{
|
|
return $"{baseUrl.TrimEnd('/')}/{relativePath.TrimStart('/')}";
|
|
}
|
|
}
|
|
|
|
class ServerFileList
|
|
{
|
|
public string VersionID { get; set; } = "";
|
|
public Dictionary<string, string> Files { get; set; } = new Dictionary<string, string>();
|
|
}
|
|
}
|
|
|