diff --git a/session-server/README.md b/session-server/README.md index 5e5c5b5..7b0d217 100644 --- a/session-server/README.md +++ b/session-server/README.md @@ -152,10 +152,14 @@ C:\apps\ - ✅ Автоматическая проверка существования exe файла - ✅ Рабочая директория устанавливается в папку приложения (`C:\apps\{appName}\`) - ✅ Окно консоли скрывается (`windowsHide: true`) +- ✅ **Запуск без графического окна** - использует флаги `-NOSPLASH` и `-NOWINDOW` для UE приложений - ✅ PID процесса отслеживается и передается на main server - ✅ Автоматическое обновление статуса при завершении процесса -- ✅ **Корректное завершение дочерних процессов** - использует `taskkill /T` для завершения всего дерева процессов -- ✅ Решает проблему с UE5 приложениями, которые создают множественные процессы +- ✅ **Многоступенчатое завершение процессов**: + 1. Мягкое завершение (`taskkill /T`) - отправляет WM_CLOSE сообщение окнам + 2. Принудительное завершение (`taskkill /T /F`) - если мягкое не сработало + 3. PowerShell завершение - закрывает окна и убивает процесс через PowerShell +- ✅ Решает проблему с UE5 приложениями, которые создают множественные процессы и имеют графические окна #### Логи запуска diff --git a/session-server/session-server.rar b/session-server/session-server.rar index e6ed923..5e9f978 100644 Binary files a/session-server/session-server.rar and b/session-server/session-server.rar differ diff --git a/session-server/src/index.ts b/session-server/src/index.ts index f2ea430..e9d92e9 100644 --- a/session-server/src/index.ts +++ b/session-server/src/index.ts @@ -517,6 +517,8 @@ async function startApplication(session: SessionData): Promise { "-PixelStreamingH264Profile=HIGH", "-PixelStreamingWebRTCDisableReceiveAudio=true", "-PixelStreamingEncoderRateControl=VBR", + "-NOSPLASH", // Отключить splash screen + "-NOWINDOW", // Запустить без окна ], { detached: false, @@ -530,7 +532,10 @@ async function startApplication(session: SessionData): Promise { ); } else { // Local-режим: запускаем без Pixel Streaming - appProcess = spawn(appPath, [], { + appProcess = spawn(appPath, [ + "-NOSPLASH", // Отключить splash screen + "-NOWINDOW", // Запустить без окна + ], { detached: false, stdio: ["ignore", "ignore", "pipe"], windowsHide: true, @@ -681,24 +686,25 @@ async function startApplication(session: SessionData): Promise { /** * Убить процесс и всё его дерево дочерних процессов (для Windows) + * Принудительное завершение без попыток мягкого закрытия */ function killProcessTree(pid: number): void { try { - // На Windows используем taskkill с флагом /T для убийства дерева процессов - // /F - принудительное завершение - // /T - завершить указанный процесс и все дочерние процессы + // Принудительное завершение с /F + console.log( + `[${new Date().toISOString()}] 🔄 Принудительное завершение процесса PID ${pid}...` + ); execSync(`taskkill /pid ${pid} /T /F`, { stdio: "ignore", - timeout: 30000, // Увеличен таймаут до 30 секунд - windowsHide: true, // Скрыть окно консоли на Windows - killSignal: "SIGKILL", // Принудительное завершение при таймауте + timeout: 30000, // Таймаут 30 секунд + windowsHide: true, + killSignal: "SIGKILL", }); console.log( - `[${new Date().toISOString()}] ✅ Дерево процессов для PID ${pid} успешно завершено` + `[${new Date().toISOString()}] ✅ Дерево процессов для PID ${pid} успешно завершено принудительно` ); } catch (error) { // Проверяем, действительно ли процесс всё ещё существует - // Если процесс не существует, это не ошибка const processExists = checkProcessExists(pid); if (!processExists) { console.log( @@ -712,13 +718,25 @@ function killProcessTree(pid: number): void { error instanceof Error ? error.message : error ); - // Попытка принудительного завершения через PowerShell как запасной вариант + // Попытка принудительного завершения через PowerShell как последний вариант try { console.log( `[${new Date().toISOString()}] 🔄 Попытка принудительного завершения через PowerShell для PID ${pid}` ); + + // Используем агрессивный PowerShell скрипт для принудительного завершения + const psScript = ` + $proc = Get-Process -Id ${pid} -ErrorAction SilentlyContinue; + if ($proc) { + # Принудительно завершаем процесс и все дочерние + Stop-Process -Id ${pid} -Force -ErrorAction SilentlyContinue; + # Завершаем все дочерние процессы + Get-Process | Where-Object { $_.Parent.Id -eq ${pid} } | Stop-Process -Force -ErrorAction SilentlyContinue; + } + `.replace(/\n/g, " "); + execSync( - `powershell -Command "Stop-Process -Id ${pid} -Force -ErrorAction SilentlyContinue"`, + `powershell -Command "${psScript}"`, { stdio: "ignore", timeout: 15000,