fix(launcher): браузер убивал сервер, установщик запускал десктоп вместо веба

1. Главное: ERR_CONNECTION_REFUSED в окне приложения.
   browserProc.WaitForExit() возвращался МГНОВЕННО, когда Edge уже был
   запущен: новый msedge.exe передаёт окно работающему экземпляру и сразу
   завершается. Лаунчер считал, что окно закрыли, и убивал сервер, пока
   страница ещё грузилась.
   Браузер теперь запускается с отдельным профилем (--user-data-dir), то
   есть процесс живёт столько же, сколько окно. Плюс подстраховка: выход
   браузера быстрее пяти секунд не считается закрытием окна.
   Та же ловушка была в Linux-лаунчере — исправлена там же.

   Проверено вживую: сервер отвечает 200 И окно приложения живо
   («Hermes Hub — Панель управления»).

2. Установщик по галочке «Запустить сейчас» открывал ДЕСКТОП. Владелец
   получал десктопное окно и принимал его за старую версию — внешне оно
   и правда другое. Теперь запускается веб-интерфейс, подпись галочки
   уточнена. Десктоп остаётся доступен своим ярлыком.

Тесты: 373 passed, ruff чисто. Установщик пересобран.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hermes Team 2026-08-24 10:07:33 +07:00
parent ef6a9e1acd
commit bca88a56a6
5 changed files with 41 additions and 7 deletions

View file

@ -18,7 +18,7 @@ namespace HermesHubSetup
// Подставляется сборщиком из фактического git-коммита. Раньше здесь
// жил зашитый "8cddc9f", то есть манифест сообщал неправду о том, из
// какого кода собран установщик.
public const string BuildCommit = "57e7ca2";
public const string BuildCommit = "ef6a9e1";
public const string MIN_HERMES_VERSION = "0.20.0";
public const string MAX_TESTED_HERMES = "0.20.4";
@ -993,7 +993,7 @@ namespace HermesHubSetup
lblDone.Height = 140;
chkLaunchNow = new CheckBox();
chkLaunchNow.Text = "Запустить Hermes Hub сейчас";
chkLaunchNow.Text = "Запустить веб-интерфейс Hermes Hub сейчас";
chkLaunchNow.Checked = true;
chkLaunchNow.Location = new Point(0, 150);
chkLaunchNow.AutoSize = true;
@ -1030,10 +1030,19 @@ namespace HermesHubSetup
{
if (chkLaunchNow != null && chkLaunchNow.Checked)
{
string exe = Path.Combine(SetupEngine.TargetInstallDir, "HermesHub.exe");
if (File.Exists(exe))
// Запускаем ВЕБ-интерфейс, а не десктоп. Владелец после
// установки получал десктопное окно и принимал его за старую
// версию: внешне оно и правда другое. Веб — то, ради чего
// ставили; десктоп остаётся доступен своим ярлыком.
string webExe = Path.Combine(SetupEngine.TargetInstallDir, "HermesHubWeb.exe");
string desktopExe = Path.Combine(SetupEngine.TargetInstallDir, "HermesHub.exe");
if (File.Exists(webExe))
{
Process.Start(exe);
Process.Start(webExe);
}
else if (File.Exists(desktopExe))
{
Process.Start(desktopExe);
}
}
this.Close();

Binary file not shown.

View file

@ -178,17 +178,28 @@ namespace HermesHub
// 4. Locate browser in strict priority: Edge -> Chrome -> Chromium registry -> Fallback
string browserPath = FindChromiumBrowser();
Process browserProc = null;
DateTime browserStartedAt = DateTime.UtcNow;
if (!string.IsNullOrEmpty(browserPath))
{
ProcessStartInfo browserPsi = new ProcessStartInfo();
browserPsi.FileName = browserPath;
browserPsi.Arguments = string.Format("--app=\"{0}\" --window-size=1400,900", targetUrl);
// Отдельный профиль браузера обязателен. Без него запущенный
// msedge.exe передаёт задачу УЖЕ РАБОТАЮЩЕМУ экземпляру и тут же
// завершается: WaitForExit возвращается мгновенно, лаунчер
// считает окно закрытым и убивает сервер, пока страница ещё
// грузится. Владелец видел ERR_CONNECTION_REFUSED.
string browserProfile = Path.Combine(hermesHome, "web_browser_profile");
try { Directory.CreateDirectory(browserProfile); } catch { }
browserPsi.Arguments = string.Format(
"--app=\"{0}\" --window-size=1400,900 --user-data-dir=\"{1}\" --no-first-run --no-default-browser-check",
targetUrl, browserProfile);
browserPsi.UseShellExecute = false;
try
{
browserProc = Process.Start(browserPsi);
browserStartedAt = DateTime.UtcNow;
}
catch (Exception ex)
{
@ -226,6 +237,14 @@ namespace HermesHub
}
catch { }
// Подстраховка: если процесс браузера завершился почти сразу,
// это почти наверняка передача окна другому экземпляру, а не
// закрытие пользователем. Убивать сервер в этом случае нельзя.
if (DateTime.UtcNow - browserStartedAt < TimeSpan.FromSeconds(5))
{
return;
}
try
{
if (!serverProcess.HasExited)

Binary file not shown.

View file

@ -121,7 +121,13 @@ done
if [ -n "$CHROMIUM_BIN" ]; then
# Launch in Application Window mode without address bar, tabs, or menus
"$CHROMIUM_BIN" --app="$TARGET_URL" --window-size=1400,900 "$@"
# Отдельный профиль: иначе запущенный браузер передаёт окно уже
# работающему экземпляру и сразу завершается — ожидание его закрытия
# срабатывает мгновенно. На Windows это приводило к тому, что сервер
# убивали, пока страница ещё грузилась.
BROWSER_PROFILE="$HERMES_HOME/web_browser_profile"
mkdir -p "$BROWSER_PROFILE"
"$CHROMIUM_BIN" --app="$TARGET_URL" --window-size=1400,900 --user-data-dir="$BROWSER_PROFILE" --no-first-run --no-default-browser-check "$@"
else
# Fallback to standard default browser
echo "Запуск в обычном браузере: режим приложения (без адресной строки) требует Google Chrome, Chromium или Microsoft Edge."