From ef1bc54988f0b70b5adf82248f410ef3cc82b1ee Mon Sep 17 00:00:00 2001 From: rjckkkkk <59609580+rjckkkkk@users.noreply.github.com> Date: Thu, 11 Jun 2026 07:26:32 +0000 Subject: [PATCH] Hide the deploy launcher console window on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The native runtime launches engines via `schtasks /it`, which runs the launcher .bat in a visible cmd.exe console on the interactive desktop (Session 1). Because that cmd is the engine process's parent, the console stayed open for the whole life of the deployment — users saw a "C:\WINDOWS\SYSTEM32\cmd" window pop up and linger on every deploy. Wrap the .bat in a tiny VBS launcher and run it via wscript with window style 0 (WScript.Shell.Run cmd, 0, False) so the cmd console is hidden. The engine still runs in Session 1 (GPU access intact); PID discovery by port/name is unchanged. Verified: llama-server runs (parent cmd.exe, hidden), deploy reaches ready, launcher .bat/.vbs are cleaned up. Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/runtime/native_windows.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/internal/runtime/native_windows.go b/internal/runtime/native_windows.go index 4bb06375..e9dfe21e 100644 --- a/internal/runtime/native_windows.go +++ b/internal/runtime/native_windows.go @@ -44,12 +44,25 @@ func (r *NativeRuntime) launchViaSchtasks(name string, command []string, logPath return 0, fmt.Errorf("write launcher script: %w", err) } + // Wrap the bat in a hidden-window VBS launcher so no cmd.exe console flashes + // on the interactive desktop. The bat's cmd is the engine process's parent + // and would otherwise stay visible for the whole life of the deployment. + // WScript.Shell.Run(cmd, 0, False) => window style 0 = hidden, no wait. + vbsPath := filepath.Join(r.logDir, name+"-launcher.vbs") + vbs := fmt.Sprintf("CreateObject(\"WScript.Shell\").Run \"\"\"%s\"\"\", 0, False\r\n", batPath) + if err := os.WriteFile(vbsPath, []byte(vbs), 0o644); err != nil { + os.Remove(batPath) + return 0, fmt.Errorf("write launcher vbs: %w", err) + } + // Create a one-time scheduled task with /it (interactive token). taskName := "AIMA-deploy-" + name + trCmd := fmt.Sprintf("wscript.exe //B //Nologo \"%s\"", vbsPath) createOut, err := exec.Command("schtasks", "/create", "/tn", taskName, - "/tr", batPath, "/sc", "once", "/st", "00:00", "/it", "/f").CombinedOutput() + "/tr", trCmd, "/sc", "once", "/st", "00:00", "/it", "/f").CombinedOutput() if err != nil { os.Remove(batPath) + os.Remove(vbsPath) return 0, fmt.Errorf("schtasks create: %w (output: %s)", err, string(createOut)) } @@ -58,6 +71,7 @@ func (r *NativeRuntime) launchViaSchtasks(name string, command []string, logPath if err != nil { exec.Command("schtasks", "/delete", "/tn", taskName, "/f").Run() os.Remove(batPath) + os.Remove(vbsPath) return 0, fmt.Errorf("schtasks run: %w (output: %s)", err, string(runOut)) } @@ -92,6 +106,7 @@ func (r *NativeRuntime) launchViaSchtasks(name string, command []string, logPath // Clean up scheduled task definition (engine process continues running). exec.Command("schtasks", "/delete", "/tn", taskName, "/f").Run() os.Remove(batPath) + os.Remove(vbsPath) if pid == 0 { return 0, fmt.Errorf("discover PID after schtasks launch: binary=%s port=%d", binaryName, port)