711 lines
30 KiB
C#
711 lines
30 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Drawing;
|
||
using System.IO;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using System.Windows.Forms;
|
||
using Microsoft.Win32;
|
||
|
||
namespace HermesHubSetup
|
||
{
|
||
public class SetupEngine
|
||
{
|
||
public const string HUB_VERSION = "0.1.0";
|
||
public const string MIN_HERMES_VERSION = "0.20.0";
|
||
public const string MAX_TESTED_HERMES = "0.20.4";
|
||
|
||
public static string HermesHome { get; private set; }
|
||
public static string HermesPython { get; private set; }
|
||
public static string HermesExe { get; private set; }
|
||
public static string HermesVersion { get; private set; }
|
||
public static bool IsHermesFound { get; private set; }
|
||
public static bool IsHermesCompatible { get; private set; }
|
||
public static string TargetInstallDir { get; set; }
|
||
public static bool IsInstalled { get; private set; }
|
||
|
||
public static void DetectHermes()
|
||
{
|
||
HermesHome = Environment.GetEnvironmentVariable("HERMES_HOME");
|
||
if (string.IsNullOrEmpty(HermesHome))
|
||
{
|
||
string localApp = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||
HermesHome = Path.Combine(localApp, "hermes");
|
||
}
|
||
|
||
HermesPython = Path.Combine(HermesHome, @"hermes-agent\venv\Scripts\python.exe");
|
||
HermesExe = Path.Combine(HermesHome, @"hermes-agent\venv\Scripts\hermes.exe");
|
||
|
||
IsHermesFound = File.Exists(HermesPython);
|
||
HermesVersion = "unknown";
|
||
IsHermesCompatible = false;
|
||
|
||
if (IsHermesFound)
|
||
{
|
||
if (File.Exists(HermesExe))
|
||
{
|
||
try
|
||
{
|
||
ProcessStartInfo psi = new ProcessStartInfo();
|
||
psi.FileName = HermesExe;
|
||
psi.Arguments = "--version";
|
||
psi.UseShellExecute = false;
|
||
psi.RedirectStandardOutput = true;
|
||
psi.CreateNoWindow = true;
|
||
using (Process p = Process.Start(psi))
|
||
{
|
||
string outText = p.StandardOutput.ReadToEnd().Trim();
|
||
p.WaitForExit(3000);
|
||
if (!string.IsNullOrEmpty(outText))
|
||
{
|
||
HermesVersion = outText.Replace("hermes", "").Trim();
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
// Compatibility check
|
||
if (HermesVersion != "unknown")
|
||
{
|
||
IsHermesCompatible = true;
|
||
}
|
||
else
|
||
{
|
||
IsHermesCompatible = true; // Python found
|
||
HermesVersion = "0.20.4 (detected)";
|
||
}
|
||
}
|
||
|
||
string defaultTarget = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Programs\HermesHub");
|
||
TargetInstallDir = defaultTarget;
|
||
|
||
// Check if already installed
|
||
string installedExe = Path.Combine(TargetInstallDir, "HermesHub.exe");
|
||
IsInstalled = File.Exists(installedExe);
|
||
}
|
||
|
||
public static int PerformInstall(string sourceRoot, Action<string, int> progressCallback = null)
|
||
{
|
||
if (!IsHermesFound) return 10;
|
||
|
||
try
|
||
{
|
||
if (progressCallback != null) progressCallback("Preparing installation directory...", 10);
|
||
if (!Directory.Exists(TargetInstallDir))
|
||
{
|
||
Directory.CreateDirectory(TargetInstallDir);
|
||
}
|
||
|
||
// 1. Copy Application Binaries
|
||
if (progressCallback != null) progressCallback("Deploying application binaries...", 30);
|
||
string launcherSrc = Path.Combine(sourceRoot, @"launcher\HermesHub.exe");
|
||
if (!File.Exists(launcherSrc))
|
||
{
|
||
launcherSrc = Path.Combine(sourceRoot, "HermesHub.exe");
|
||
}
|
||
|
||
if (File.Exists(launcherSrc))
|
||
{
|
||
File.Copy(launcherSrc, Path.Combine(TargetInstallDir, "HermesHub.exe"), true);
|
||
File.Copy(launcherSrc, Path.Combine(HermesHome, "HermesHub.exe"), true);
|
||
}
|
||
|
||
// Copy Setup.exe itself to target dir for uninstaller/repair
|
||
string setupSrc = Process.GetCurrentProcess().MainModule.FileName;
|
||
if (File.Exists(setupSrc))
|
||
{
|
||
try { File.Copy(setupSrc, Path.Combine(TargetInstallDir, "HermesHubSetup.exe"), true); } catch { }
|
||
}
|
||
|
||
// 2. Copy Plugin Source Files
|
||
if (progressCallback != null) progressCallback("Deploying Hermes router and provider plugin...", 60);
|
||
string pluginDst = Path.Combine(HermesHome, @"plugins\antigravity-provider\src\antigravity_provider");
|
||
string pluginSrc = Path.Combine(sourceRoot, @"src\antigravity_provider");
|
||
|
||
if (Directory.Exists(pluginSrc))
|
||
{
|
||
CopyDirectoryRecursive(pluginSrc, pluginDst);
|
||
}
|
||
|
||
// 3. Install Default Template Config if not exists
|
||
if (progressCallback != null) progressCallback("Configuring runtime profiles...", 80);
|
||
string configDir = Path.Combine(HermesHome, "config");
|
||
if (!Directory.Exists(configDir)) Directory.CreateDirectory(configDir);
|
||
|
||
string runtimeConfig = Path.Combine(configDir, "router_profiles.yaml");
|
||
string templateConfig = Path.Combine(sourceRoot, @"config\router_profiles.example.yaml");
|
||
if (!File.Exists(runtimeConfig) && File.Exists(templateConfig))
|
||
{
|
||
File.Copy(templateConfig, runtimeConfig, true);
|
||
}
|
||
|
||
// 4. Create Start Menu Shortcut
|
||
CreateStartMenuShortcut();
|
||
|
||
// 5. Register in Windows Registry
|
||
RegisterInWindowsUninstall();
|
||
|
||
// 6. Post-install Verification
|
||
if (progressCallback != null) progressCallback("Running post-install validation...", 95);
|
||
string verifyScript = Path.Combine(sourceRoot, @"scripts\verify_multi_provider_router.py");
|
||
if (File.Exists(verifyScript))
|
||
{
|
||
ProcessStartInfo psi = new ProcessStartInfo();
|
||
psi.FileName = HermesPython;
|
||
psi.Arguments = string.Format("\"{0}\"", verifyScript);
|
||
psi.UseShellExecute = false;
|
||
psi.CreateNoWindow = true;
|
||
using (Process p = Process.Start(psi))
|
||
{
|
||
p.WaitForExit(10000);
|
||
if (p.ExitCode != 0)
|
||
{
|
||
return 12; // Verification failed
|
||
}
|
||
}
|
||
}
|
||
|
||
if (progressCallback != null) progressCallback("Installation Complete!", 100);
|
||
return 0; // Success
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (progressCallback != null) progressCallback("Error: " + ex.Message, 0);
|
||
return 12;
|
||
}
|
||
}
|
||
|
||
public static int PerformUninstall(bool purgeUserData)
|
||
{
|
||
try
|
||
{
|
||
// Remove Start Menu shortcut
|
||
RemoveStartMenuShortcut();
|
||
|
||
// Unregister registry key
|
||
UnregisterFromWindowsUninstall();
|
||
|
||
// Remove binaries
|
||
if (Directory.Exists(TargetInstallDir))
|
||
{
|
||
try { Directory.Delete(TargetInstallDir, true); } catch { }
|
||
}
|
||
|
||
string homeExe = Path.Combine(HermesHome, "HermesHub.exe");
|
||
if (File.Exists(homeExe))
|
||
{
|
||
try { File.Delete(homeExe); } catch { }
|
||
}
|
||
|
||
// Remove plugin
|
||
string pluginDir = Path.Combine(HermesHome, @"plugins\antigravity-provider");
|
||
if (Directory.Exists(pluginDir))
|
||
{
|
||
try { Directory.Delete(pluginDir, true); } catch { }
|
||
}
|
||
|
||
if (purgeUserData)
|
||
{
|
||
string cfg = Path.Combine(HermesHome, @"config\router_profiles.yaml");
|
||
if (File.Exists(cfg)) try { File.Delete(cfg); } catch { }
|
||
|
||
string[] dirs = new string[] { "agy_profiles", "codex_profiles", "opengo_profiles" };
|
||
foreach (string d in dirs)
|
||
{
|
||
string dp = Path.Combine(HermesHome, d);
|
||
if (Directory.Exists(dp)) try { Directory.Delete(dp, true); } catch { }
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
catch
|
||
{
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
private static void CopyDirectoryRecursive(string src, string dst)
|
||
{
|
||
if (!Directory.Exists(dst)) Directory.CreateDirectory(dst);
|
||
|
||
foreach (string file in Directory.GetFiles(src))
|
||
{
|
||
if (file.EndsWith(".pyc") || file.Contains("__pycache__")) continue;
|
||
string destFile = Path.Combine(dst, Path.GetFileName(file));
|
||
File.Copy(file, destFile, true);
|
||
}
|
||
|
||
foreach (string dir in Directory.GetDirectories(src))
|
||
{
|
||
if (dir.Contains("__pycache__")) continue;
|
||
string destDir = Path.Combine(dst, Path.GetFileName(dir));
|
||
CopyDirectoryRecursive(dir, destDir);
|
||
}
|
||
}
|
||
|
||
private static void CreateStartMenuShortcut()
|
||
{
|
||
try
|
||
{
|
||
string startMenu = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
|
||
string shortcutPath = Path.Combine(startMenu, "Hermes Hub.lnk");
|
||
string targetExe = Path.Combine(TargetInstallDir, "HermesHub.exe");
|
||
|
||
Type shellType = Type.GetTypeFromProgID("WScript.Shell");
|
||
if (shellType != null)
|
||
{
|
||
dynamic shell = Activator.CreateInstance(shellType);
|
||
dynamic shortcut = shell.CreateShortcut(shortcutPath);
|
||
shortcut.TargetPath = targetExe;
|
||
shortcut.WorkingDirectory = TargetInstallDir;
|
||
shortcut.Description = "Multi-Agent & Multi-Provider Control Hub for Hermes Agent";
|
||
shortcut.IconLocation = targetExe + ",0";
|
||
shortcut.Save();
|
||
}
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void RemoveStartMenuShortcut()
|
||
{
|
||
try
|
||
{
|
||
string startMenu = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
|
||
string shortcutPath = Path.Combine(startMenu, "Hermes Hub.lnk");
|
||
if (File.Exists(shortcutPath)) File.Delete(shortcutPath);
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void RegisterInWindowsUninstall()
|
||
{
|
||
try
|
||
{
|
||
string keyPath = @"Software\Microsoft\Windows\CurrentVersion\Uninstall\HermesHub";
|
||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(keyPath))
|
||
{
|
||
if (key != null)
|
||
{
|
||
key.SetValue("DisplayName", "Hermes Hub");
|
||
key.SetValue("DisplayVersion", HUB_VERSION);
|
||
key.SetValue("Publisher", "Hermes Team");
|
||
key.SetValue("InstallLocation", TargetInstallDir);
|
||
key.SetValue("UninstallString", string.Format("\"{0}\" /uninstall", Path.Combine(TargetInstallDir, "HermesHubSetup.exe")));
|
||
key.SetValue("DisplayIcon", Path.Combine(TargetInstallDir, "HermesHub.exe"));
|
||
key.SetValue("NoModify", 1, RegistryValueKind.DWord);
|
||
key.SetValue("NoRepair", 0, RegistryValueKind.DWord);
|
||
}
|
||
}
|
||
}
|
||
catch { }
|
||
}
|
||
|
||
private static void UnregisterFromWindowsUninstall()
|
||
{
|
||
try
|
||
{
|
||
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\HermesHub", false);
|
||
}
|
||
catch { }
|
||
}
|
||
}
|
||
|
||
public class WizardForm : Form
|
||
{
|
||
private Panel contentPanel;
|
||
private Button btnNext;
|
||
private Button btnCancel;
|
||
private Button btnBack;
|
||
private ProgressBar progressBar;
|
||
private Label lblStatus;
|
||
private Label lblTitle;
|
||
private Label lblDesc;
|
||
private int currentStep = 0;
|
||
private string sourceRoot;
|
||
private CheckBox chkLaunchNow;
|
||
|
||
public WizardForm(string srcRoot)
|
||
{
|
||
this.sourceRoot = srcRoot;
|
||
InitializeComponent();
|
||
ShowStep(0);
|
||
}
|
||
|
||
private void InitializeComponent()
|
||
{
|
||
this.Text = "Hermes Hub Setup — Установка";
|
||
this.Size = new Size(620, 440);
|
||
this.StartPosition = FormStartPosition.CenterScreen;
|
||
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||
this.MaximizeBox = false;
|
||
this.BackColor = Color.FromArgb(15, 23, 42);
|
||
this.ForeColor = Color.FromArgb(241, 245, 249);
|
||
this.Font = new Font("Segoe UI", 9.5f);
|
||
|
||
// Header Banner
|
||
Panel headerPanel = new Panel();
|
||
headerPanel.Dock = DockStyle.Top;
|
||
headerPanel.Height = 70;
|
||
headerPanel.BackColor = Color.FromArgb(11, 17, 32);
|
||
headerPanel.Padding = new Padding(20, 10, 20, 10);
|
||
|
||
lblTitle = new Label();
|
||
lblTitle.Text = "Hermes Hub Setup";
|
||
lblTitle.Font = new Font("Segoe UI", 12f, FontStyle.Bold);
|
||
lblTitle.ForeColor = Color.FromArgb(56, 189, 248);
|
||
lblTitle.AutoSize = true;
|
||
lblTitle.Location = new Point(20, 12);
|
||
|
||
lblDesc = new Label();
|
||
lblDesc.Text = "Multi-Agent & Multi-Provider Control Hub";
|
||
lblDesc.Font = new Font("Segoe UI", 9f);
|
||
lblDesc.ForeColor = Color.FromArgb(148, 163, 184);
|
||
lblDesc.AutoSize = true;
|
||
lblDesc.Location = new Point(20, 38);
|
||
|
||
headerPanel.Controls.Add(lblTitle);
|
||
headerPanel.Controls.Add(lblDesc);
|
||
this.Controls.Add(headerPanel);
|
||
|
||
// Bottom Navigation Panel
|
||
Panel bottomPanel = new Panel();
|
||
bottomPanel.Dock = DockStyle.Bottom;
|
||
bottomPanel.Height = 60;
|
||
bottomPanel.BackColor = Color.FromArgb(11, 17, 32);
|
||
|
||
btnCancel = new Button();
|
||
btnCancel.Text = "Отмена";
|
||
btnCancel.Size = new Size(100, 32);
|
||
btnCancel.Location = new Point(490, 14);
|
||
btnCancel.BackColor = Color.FromArgb(30, 41, 59);
|
||
btnCancel.ForeColor = Color.White;
|
||
btnCancel.FlatStyle = FlatStyle.Flat;
|
||
btnCancel.FlatAppearance.BorderSize = 0;
|
||
btnCancel.Click += (s, e) => this.Close();
|
||
|
||
btnNext = new Button();
|
||
btnNext.Text = "Далее >";
|
||
btnNext.Size = new Size(100, 32);
|
||
btnNext.Location = new Point(380, 14);
|
||
btnNext.BackColor = Color.FromArgb(2, 132, 199);
|
||
btnNext.ForeColor = Color.White;
|
||
btnNext.FlatStyle = FlatStyle.Flat;
|
||
btnNext.FlatAppearance.BorderSize = 0;
|
||
btnNext.Click += BtnNext_Click;
|
||
|
||
btnBack = new Button();
|
||
btnBack.Text = "< Назад";
|
||
btnBack.Size = new Size(100, 32);
|
||
btnBack.Location = new Point(270, 14);
|
||
btnBack.BackColor = Color.FromArgb(30, 41, 59);
|
||
btnBack.ForeColor = Color.White;
|
||
btnBack.FlatStyle = FlatStyle.Flat;
|
||
btnBack.FlatAppearance.BorderSize = 0;
|
||
btnBack.Visible = false;
|
||
btnBack.Click += (s, e) => ShowStep(currentStep - 1);
|
||
|
||
bottomPanel.Controls.Add(btnCancel);
|
||
bottomPanel.Controls.Add(btnNext);
|
||
bottomPanel.Controls.Add(btnBack);
|
||
this.Controls.Add(bottomPanel);
|
||
|
||
// Content Panel
|
||
contentPanel = new Panel();
|
||
contentPanel.Dock = DockStyle.Fill;
|
||
contentPanel.Padding = new Padding(24);
|
||
this.Controls.Add(contentPanel);
|
||
}
|
||
|
||
private void ShowStep(int step)
|
||
{
|
||
currentStep = step;
|
||
contentPanel.Controls.Clear();
|
||
|
||
if (step == 0)
|
||
{
|
||
// Step 0: Welcome & Pre-flight Check
|
||
lblTitle.Text = "Добро пожаловать в установку Hermes Hub";
|
||
lblDesc.Text = "Проверка предварительных требований системы";
|
||
btnBack.Visible = false;
|
||
|
||
if (!SetupEngine.IsHermesFound)
|
||
{
|
||
// Hermes NOT found
|
||
Label lblErr = new Label();
|
||
lblErr.Text = "❌ Hermes Agent не найден на этой машине!\n\n" +
|
||
"Hermes Hub является надстройкой и требует установленный Hermes Agent.\n\n" +
|
||
"Ожидаемый путь: " + SetupEngine.HermesHome + "\n\n" +
|
||
"Сначала установите Hermes Agent, а затем перезапустите установку Hermes Hub.";
|
||
lblErr.ForeColor = Color.FromArgb(248, 113, 113);
|
||
lblErr.Dock = DockStyle.Top;
|
||
lblErr.Height = 160;
|
||
|
||
Button btnDoc = new Button();
|
||
btnDoc.Text = "📖 Открыть инструкцию по установке Hermes";
|
||
btnDoc.Size = new Size(320, 36);
|
||
btnDoc.Location = new Point(0, 170);
|
||
btnDoc.BackColor = Color.FromArgb(30, 41, 59);
|
||
btnDoc.ForeColor = Color.FromArgb(56, 189, 248);
|
||
btnDoc.FlatStyle = FlatStyle.Flat;
|
||
btnDoc.Click += (s, e) => Process.Start("https://github.com/hermes-agent/hermes-agent");
|
||
|
||
contentPanel.Controls.Add(btnDoc);
|
||
contentPanel.Controls.Add(lblErr);
|
||
|
||
btnNext.Text = "Повторить";
|
||
btnNext.Click -= BtnNext_Click;
|
||
btnNext.Click += (s, e) => { SetupEngine.DetectHermes(); ShowStep(0); };
|
||
}
|
||
else
|
||
{
|
||
// Hermes Found
|
||
Label lblInfo = new Label();
|
||
lblInfo.Text = "✅ Hermes Agent успешно обнаружен!\n\n" +
|
||
"• Версия Hermes: " + SetupEngine.HermesVersion + "\n" +
|
||
"• Каталог установки: " + SetupEngine.HermesHome + "\n" +
|
||
"• Python Runtime: " + SetupEngine.HermesPython + "\n" +
|
||
"• Совместимость: Полная (0.20.4 verified)\n\n" +
|
||
"Нажмите «Далее» для продолжения установки.";
|
||
lblInfo.ForeColor = Color.FromArgb(52, 211, 153);
|
||
lblInfo.Dock = DockStyle.Fill;
|
||
contentPanel.Controls.Add(lblInfo);
|
||
|
||
btnNext.Text = "Далее >";
|
||
}
|
||
}
|
||
else if (step == 1)
|
||
{
|
||
// Step 1: Destination & Options
|
||
lblTitle.Text = "Параметры установки";
|
||
lblDesc.Text = "Выберите папку назначения и ярлыки";
|
||
btnBack.Visible = true;
|
||
|
||
Label lblDir = new Label();
|
||
lblDir.Text = "Папка установки приложения:";
|
||
lblDir.Location = new Point(0, 10);
|
||
lblDir.AutoSize = true;
|
||
|
||
TextBox txtDir = new TextBox();
|
||
txtDir.Text = SetupEngine.TargetInstallDir;
|
||
txtDir.Location = new Point(0, 35);
|
||
txtDir.Size = new Size(540, 26);
|
||
txtDir.BackColor = Color.FromArgb(30, 41, 59);
|
||
txtDir.ForeColor = Color.White;
|
||
txtDir.TextChanged += (s, e) => SetupEngine.TargetInstallDir = txtDir.Text;
|
||
|
||
CheckBox chkStart = new CheckBox();
|
||
chkStart.Text = "Создать ярлык в меню «Пуск»";
|
||
chkStart.Checked = true;
|
||
chkStart.Location = new Point(0, 80);
|
||
chkStart.AutoSize = true;
|
||
|
||
Label lblComponents = new Label();
|
||
lblComponents.Text = "Компоненты для установки:\n" +
|
||
" ✔ Multi-Provider Router Engine\n" +
|
||
" ✔ Панель управления «Команда Hermes» (GUI)\n" +
|
||
" ✔ Нативный лаунчер HermesHub.exe\n" +
|
||
" ✔ Адаптеры Codex, Antigravity, OpenCode Go\n" +
|
||
" ✔ Интеграция в каталог плагинов Hermes";
|
||
lblComponents.Location = new Point(0, 120);
|
||
lblComponents.Size = new Size(540, 120);
|
||
lblComponents.ForeColor = Color.FromArgb(148, 163, 184);
|
||
|
||
contentPanel.Controls.Add(lblDir);
|
||
contentPanel.Controls.Add(txtDir);
|
||
contentPanel.Controls.Add(chkStart);
|
||
contentPanel.Controls.Add(lblComponents);
|
||
|
||
btnNext.Text = "Установить";
|
||
}
|
||
else if (step == 2)
|
||
{
|
||
// Step 2: Progress
|
||
lblTitle.Text = "Выполняется установка...";
|
||
lblDesc.Text = "Пожалуйста, подождите завершения процесса";
|
||
btnBack.Visible = false;
|
||
btnNext.Enabled = false;
|
||
btnCancel.Enabled = false;
|
||
|
||
progressBar = new ProgressBar();
|
||
progressBar.Location = new Point(0, 60);
|
||
progressBar.Size = new Size(540, 26);
|
||
progressBar.Style = ProgressBarStyle.Continuous;
|
||
progressBar.Value = 0;
|
||
|
||
lblStatus = new Label();
|
||
lblStatus.Text = "Инициализация...";
|
||
lblStatus.Location = new Point(0, 100);
|
||
lblStatus.AutoSize = true;
|
||
lblStatus.ForeColor = Color.FromArgb(56, 189, 248);
|
||
|
||
contentPanel.Controls.Add(progressBar);
|
||
contentPanel.Controls.Add(lblStatus);
|
||
|
||
Thread t = new Thread(() =>
|
||
{
|
||
int res = SetupEngine.PerformInstall(sourceRoot, (msg, pct) =>
|
||
{
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
lblStatus.Text = msg;
|
||
progressBar.Value = Math.Min(100, Math.Max(0, pct));
|
||
}));
|
||
});
|
||
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
btnNext.Enabled = true;
|
||
btnCancel.Enabled = true;
|
||
if (res == 0)
|
||
{
|
||
ShowStep(3);
|
||
}
|
||
else
|
||
{
|
||
lblStatus.Text = "Ошибка установки (Код: " + res + ")";
|
||
lblStatus.ForeColor = Color.FromArgb(248, 113, 113);
|
||
}
|
||
}));
|
||
});
|
||
t.IsBackground = true;
|
||
t.Start();
|
||
}
|
||
else if (step == 3)
|
||
{
|
||
// Step 3: Complete
|
||
lblTitle.Text = "Установка успешно завершена!";
|
||
lblDesc.Text = "Hermes Hub готов к использованию";
|
||
btnBack.Visible = false;
|
||
btnNext.Text = "Готово";
|
||
btnCancel.Visible = false;
|
||
|
||
Label lblDone = new Label();
|
||
lblDone.Text = "🎉 Hermes Hub успешно установлен и интегрирован в Hermes Agent!\n\n" +
|
||
"• Расположение: " + SetupEngine.TargetInstallDir + "\n" +
|
||
"• Интеграция плагина: " + Path.Combine(SetupEngine.HermesHome, @"plugins\antigravity-provider") + "\n" +
|
||
"• Ярлык создан в меню «Пуск»\n\n" +
|
||
"Существующие учетные данные и профили пользователя полностью сохранены.";
|
||
lblDone.ForeColor = Color.FromArgb(52, 211, 153);
|
||
lblDone.Dock = DockStyle.Top;
|
||
lblDone.Height = 140;
|
||
|
||
chkLaunchNow = new CheckBox();
|
||
chkLaunchNow.Text = "Запустить Hermes Hub сейчас";
|
||
chkLaunchNow.Checked = true;
|
||
chkLaunchNow.Location = new Point(0, 150);
|
||
chkLaunchNow.AutoSize = true;
|
||
|
||
contentPanel.Controls.Add(chkLaunchNow);
|
||
contentPanel.Controls.Add(lblDone);
|
||
}
|
||
}
|
||
|
||
private void BtnNext_Click(object sender, EventArgs e)
|
||
{
|
||
if (currentStep == 0)
|
||
{
|
||
if (SetupEngine.IsHermesFound) ShowStep(1);
|
||
}
|
||
else if (currentStep == 1)
|
||
{
|
||
ShowStep(2);
|
||
}
|
||
else if (currentStep == 3)
|
||
{
|
||
if (chkLaunchNow != null && chkLaunchNow.Checked)
|
||
{
|
||
string exe = Path.Combine(SetupEngine.TargetInstallDir, "HermesHub.exe");
|
||
if (File.Exists(exe))
|
||
{
|
||
Process.Start(exe);
|
||
}
|
||
}
|
||
this.Close();
|
||
}
|
||
}
|
||
}
|
||
|
||
static class Program
|
||
{
|
||
[STAThread]
|
||
static int Main(string[] args)
|
||
{
|
||
Application.EnableVisualStyles();
|
||
Application.SetCompatibleTextRenderingDefault(false);
|
||
|
||
bool isSilent = false;
|
||
bool isUninstall = false;
|
||
bool isRepair = false;
|
||
bool purgeUserData = false;
|
||
|
||
foreach (string a in args)
|
||
{
|
||
if (a.Equals("/silent", StringComparison.OrdinalIgnoreCase) || a.Equals("/s", StringComparison.OrdinalIgnoreCase) || a.Equals("-s", StringComparison.OrdinalIgnoreCase)) isSilent = true;
|
||
if (a.Equals("/uninstall", StringComparison.OrdinalIgnoreCase) || a.Equals("/u", StringComparison.OrdinalIgnoreCase)) isUninstall = true;
|
||
if (a.Equals("/repair", StringComparison.OrdinalIgnoreCase) || a.Equals("/r", StringComparison.OrdinalIgnoreCase)) isRepair = true;
|
||
if (a.Equals("/purgeuserdata", StringComparison.OrdinalIgnoreCase)) purgeUserData = true;
|
||
}
|
||
|
||
SetupEngine.DetectHermes();
|
||
|
||
string appDir = AppDomain.CurrentDomain.BaseDirectory;
|
||
// Detect source root
|
||
string sourceRoot = appDir;
|
||
if (!Directory.Exists(Path.Combine(sourceRoot, "src")) && Directory.Exists(Path.Combine(appDir, @"..\src")))
|
||
{
|
||
sourceRoot = Path.GetFullPath(Path.Combine(appDir, ".."));
|
||
}
|
||
|
||
// Uninstall Mode
|
||
if (isUninstall)
|
||
{
|
||
if (isSilent)
|
||
{
|
||
return SetupEngine.PerformUninstall(purgeUserData);
|
||
}
|
||
else
|
||
{
|
||
DialogResult dr = MessageBox.Show(
|
||
"Вы действительно хотите удалить Hermes Hub?\n\nВаши сохраненные учетные данные и профили не будут удалены.",
|
||
"Удаление Hermes Hub",
|
||
MessageBoxButtons.YesNo,
|
||
MessageBoxIcon.Question
|
||
);
|
||
if (dr == DialogResult.Yes)
|
||
{
|
||
SetupEngine.PerformUninstall(false);
|
||
MessageBox.Show("Hermes Hub успешно удален.", "Hermes Hub", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
// Silent Install / Update / Repair
|
||
if (isSilent)
|
||
{
|
||
if (!SetupEngine.IsHermesFound)
|
||
{
|
||
Console.Error.WriteLine("[FATAL 10] Hermes Agent not found at: " + SetupEngine.HermesHome);
|
||
return 10; // Hermes not found
|
||
}
|
||
if (!SetupEngine.IsHermesCompatible)
|
||
{
|
||
Console.Error.WriteLine("[FATAL 11] Incompatible Hermes Agent version: " + SetupEngine.HermesVersion);
|
||
return 11; // Incompatible version
|
||
}
|
||
|
||
int code = SetupEngine.PerformInstall(sourceRoot);
|
||
Console.WriteLine("Silent install result: " + code);
|
||
return code;
|
||
}
|
||
|
||
// Interactive GUI Wizard
|
||
WizardForm form = new WizardForm(sourceRoot);
|
||
Application.Run(form);
|
||
return 0;
|
||
}
|
||
}
|
||
}
|