304 lines
10 KiB
C#
304 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Reflection.Emit;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using Newtonsoft.Json;
|
|
using System.Security.Cryptography;
|
|
using System.Net.Http;
|
|
using Microsoft.Win32;
|
|
using System.Security.Policy;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace StudioClient
|
|
{
|
|
public partial class Form1 : Form
|
|
{
|
|
static string serverUrl = "http://xr.flexing.ai:3030/XR_Server/";
|
|
|
|
static string appName_Studio = "Studio";
|
|
static string appName_StudioTwin = "StudioTwin";
|
|
static string appName_StudioSimulator = "StudioSimulator";
|
|
|
|
static string setupFileTag = "Setup.exe";
|
|
|
|
static readonly HttpClient httpClient = new HttpClient();
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
public static extern uint RegisterWindowMessage(string lpString);
|
|
|
|
private uint installCompleteMsg;
|
|
private uint uninstallCompleteMsg;
|
|
|
|
public Form1()
|
|
{
|
|
InitializeComponent();
|
|
|
|
Initialize();
|
|
}
|
|
|
|
void Initialize()
|
|
{
|
|
installCompleteMsg = RegisterWindowMessage($@"INSTALL_COMPLETE");
|
|
uninstallCompleteMsg = RegisterWindowMessage($@"UNINSTALL_COMPLETE");
|
|
|
|
string installPath;
|
|
|
|
installPath = GetInstalledPathFromRegistry(appName_Studio);
|
|
if (!string.IsNullOrWhiteSpace(installPath) && Directory.Exists(installPath))
|
|
{
|
|
SetButtonState(true, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
|
|
}
|
|
else
|
|
{
|
|
SetButtonState(false, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
|
|
}
|
|
}
|
|
|
|
void SetButtonState(bool isInstallComplete, Button installButton, Button checkButton, Button deleteButton)
|
|
{
|
|
if (isInstallComplete)
|
|
{
|
|
installButton.Text = "실행";
|
|
checkButton.Visible = true;
|
|
checkButton.Enabled = true;
|
|
deleteButton.Visible = true;
|
|
deleteButton.Enabled = true;
|
|
}
|
|
else
|
|
{
|
|
installButton.Text = "설치";
|
|
checkButton.Visible = false;
|
|
checkButton.Enabled = false;
|
|
deleteButton.Visible = false;
|
|
deleteButton.Enabled = false;
|
|
}
|
|
}
|
|
|
|
private async void StudioInstallButton_Click(object sender, EventArgs e)
|
|
{
|
|
await OnClickButton(appName_Studio);
|
|
}
|
|
|
|
private async void StudioTwinInstallButton_Click(object sender, EventArgs e)
|
|
{
|
|
//await InstallApp(serverUrl, appName_StudioTwin);
|
|
}
|
|
|
|
private async void StudioSimulatorInstallButton_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private async void StudioCheckButton_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private async void StudioDeleteButton_Click(object sender, EventArgs e)
|
|
{
|
|
await UninstallApp(appName_Studio);
|
|
}
|
|
|
|
private async void StudioTwinDeleteButton_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private async void StudioSimulatorDeleteButton_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private async void WriteText(string text)
|
|
{
|
|
label1.Text = text;
|
|
}
|
|
|
|
private async Task OnClickButton(string appName)
|
|
{
|
|
string appUrl = Path.Combine(serverUrl, appName);
|
|
|
|
// 이미 Setup으로 설치를 진행했는지 체크
|
|
string installPath = GetInstalledPathFromRegistry(appName);
|
|
string exeFilePath;
|
|
|
|
if (!string.IsNullOrWhiteSpace(installPath) && Directory.Exists(installPath)) // 이미 설치 되있으면 경로에서 exe파일 실행
|
|
{
|
|
WriteText("런처 실행");
|
|
|
|
exeFilePath = Directory.GetFiles(installPath, "*.exe", SearchOption.TopDirectoryOnly)
|
|
.FirstOrDefault(file =>
|
|
!Path.GetFileName(file).Equals("unins000.exe", StringComparison.OrdinalIgnoreCase) &&
|
|
Path.GetFileName(file).IndexOf("Launcher", StringComparison.OrdinalIgnoreCase) >= 0);
|
|
|
|
|
|
if (string.IsNullOrEmpty(exeFilePath))
|
|
{
|
|
WriteText("❌ 설치 경로에 실행할 수 있는 런처의 exe 파일이 없습니다.");
|
|
return;
|
|
}
|
|
|
|
StartExecutableFile(exeFilePath, installPath);
|
|
}
|
|
else // 설치 안되있으면 Setup 다운받고 Setup 실행
|
|
{
|
|
WriteText("설치 진행중");
|
|
|
|
// Setup 파일이 이미 있으면 삭제하고 서버에서 새로 다운로드
|
|
string setupFileName = appName + setupFileTag;
|
|
if (File.Exists(setupFileName))
|
|
{
|
|
File.Delete(setupFileName);
|
|
}
|
|
string setupFileUrl = Path.Combine(appUrl, setupFileName);
|
|
await DownloadFile(setupFileUrl, ProgressBar);
|
|
|
|
string currentDir = AppContext.BaseDirectory;
|
|
exeFilePath = Path.Combine(currentDir, setupFileName);
|
|
StartExecutableFile(exeFilePath, currentDir);
|
|
}
|
|
}
|
|
|
|
private string GetInstalledPathFromRegistry(string appName)
|
|
{
|
|
try
|
|
{
|
|
using (RegistryKey key = Registry.CurrentUser.OpenSubKey($@"Software\UVC\{appName}"))
|
|
{
|
|
if (key != null)
|
|
{
|
|
return key.GetValue("InstallPath") as string ?? "";
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
WriteText($"❌ 레지스트리 읽기 실패 ({appName}): {ex.Message}");
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
private async Task DownloadFile(string url, ProgressBar progressBar)
|
|
{
|
|
try
|
|
{
|
|
string currentDir = AppContext.BaseDirectory;
|
|
string fileName = Path.GetFileName(new Uri(url).LocalPath);
|
|
string fullPath = Path.Combine(currentDir, fileName);
|
|
|
|
using (var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
|
|
{
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
long? totalBytes = response.Content.Headers.ContentLength;
|
|
if (totalBytes == null)
|
|
{
|
|
WriteText("❌ 파일 크기를 알 수 없습니다.");
|
|
return;
|
|
}
|
|
|
|
using (var contentStream = await response.Content.ReadAsStreamAsync())
|
|
using (var fileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
|
{
|
|
progressBar.Invoke((MethodInvoker)(() =>
|
|
{
|
|
progressBar.Minimum = 0;
|
|
progressBar.Maximum = 100;
|
|
progressBar.Value = 0;
|
|
}));
|
|
|
|
byte[] buffer = new byte[81920]; // 80KB 버퍼
|
|
long totalRead = 0;
|
|
int bytesRead;
|
|
|
|
while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
|
{
|
|
await fileStream.WriteAsync(buffer, 0, bytesRead);
|
|
totalRead += bytesRead;
|
|
|
|
int progress = (int)((totalRead * 100) / totalBytes.Value);
|
|
|
|
progressBar.Invoke((MethodInvoker)(() =>
|
|
{
|
|
progressBar.Value = Math.Min(progress, 100);
|
|
}));
|
|
}
|
|
|
|
WriteText("✅ 다운로드 완료!");
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
WriteText($"❌ 다운로드 실패: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
|
|
private void StartExecutableFile(string exeFilePath, string workingDirectory)
|
|
{
|
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
|
{
|
|
FileName = exeFilePath,
|
|
WorkingDirectory = workingDirectory,
|
|
UseShellExecute = true // Windows에서 기본 프로그램으로 실행
|
|
};
|
|
|
|
Process.Start(startInfo);
|
|
}
|
|
|
|
private async Task UninstallApp(string appName)
|
|
{
|
|
string appUrl = Path.Combine(serverUrl, appName);
|
|
|
|
// 설치가 이미 되어있는지 체크
|
|
string installPath = GetInstalledPathFromRegistry(appName);
|
|
string exeFilePath;
|
|
|
|
if (!string.IsNullOrWhiteSpace(installPath) && Directory.Exists(installPath)) // 설치 되있으면 경로에서 Uninstaller 실행
|
|
{
|
|
exeFilePath = Directory.GetFiles(installPath, "unins000.exe", SearchOption.TopDirectoryOnly).FirstOrDefault();
|
|
|
|
if (string.IsNullOrEmpty(exeFilePath))
|
|
{
|
|
WriteText("❌ 설치 경로에 실행할 수 있는 unins000.exe 파일이 없습니다.");
|
|
return;
|
|
}
|
|
|
|
WriteText("Uninstaller 실행");
|
|
|
|
StartExecutableFile(exeFilePath, installPath);
|
|
}
|
|
else
|
|
{
|
|
WriteText("❌ 설치된 경로가 없습니다.");
|
|
}
|
|
}
|
|
|
|
// Install / Uninstall 완료 시
|
|
protected override void WndProc(ref Message m)
|
|
{
|
|
if (m.Msg == installCompleteMsg)
|
|
{
|
|
SetButtonState(true, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
|
|
}
|
|
else if (m.Msg == uninstallCompleteMsg)
|
|
{
|
|
SetButtonState(false, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
|
|
}
|
|
|
|
base.WndProc(ref m);
|
|
}
|
|
}
|
|
}
|