-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix(windows): keep installed tray alive after launch #2856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ import { execFile, execFileSync, spawn } from "node:child_process"; | |
| import { createHash } from "node:crypto"; | ||
| import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs"; | ||
| import { homedir } from "node:os"; | ||
| import { join, resolve } from "node:path"; | ||
| import { join, resolve, win32 as win32Path } from "node:path"; | ||
| import { expandUserPath, getConfigDir } from "../config"; | ||
| import { durableBunRuntime } from "../lib/bun-runtime"; | ||
| import type { BunRuntimeSource } from "../lib/bun-runtime"; | ||
|
|
@@ -46,6 +46,12 @@ export interface WindowsTrayStatus { | |
| summary: string; | ||
| } | ||
|
|
||
| export type WindowsTrayLaunchRunner = ( | ||
| file: string, | ||
| args: readonly string[], | ||
| options: { stdio: "ignore"; windowsHide: true; timeout: number }, | ||
| ) => void; | ||
|
|
||
| function trayStatePath(): string { | ||
| return join(getConfigDir(), "tray-state.json"); | ||
| } | ||
|
|
@@ -506,8 +512,10 @@ const DETACHED_TRAY_HOST_LAUNCHER = [ | |
| "$startInfo = New-Object System.Diagnostics.ProcessStartInfo", | ||
| "$startInfo.FileName = $env:OCX_TRAY_HOST_BUN", | ||
| "$startInfo.Arguments = $env:OCX_TRAY_HOST_ARGS", | ||
| "$startInfo.UseShellExecute = $true", | ||
| "$startInfo.UseShellExecute = $false", | ||
| "$startInfo.CreateNoWindow = $true", | ||
| "$startInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden", | ||
| "$startInfo.EnvironmentVariables['OCX_TRAY_ENTRY_B64'] = $env:OCX_TRAY_ENTRY_B64", | ||
| "$child = [System.Diagnostics.Process]::Start($startInfo)", | ||
| "if ($null -eq $child) { throw 'Windows tray host did not start.' }", | ||
| "$child.Dispose()", | ||
|
|
@@ -537,7 +545,27 @@ export function launchWindowsTrayHost(state: WindowsTrayEntry): void { | |
| }); | ||
| } | ||
|
|
||
| export function launchInstalledWindowsTray( | ||
| launcherPath: string, | ||
| deps: { systemRoot?: string; run?: WindowsTrayLaunchRunner } = {}, | ||
| ): void { | ||
| const wscript = win32Path.join(deps.systemRoot ?? process.env.SystemRoot ?? "C:\\Windows", "System32", "wscript.exe"); | ||
| const run = deps.run ?? ((file, args, options) => { | ||
| execFileSync(file, [...args], options); | ||
| }); | ||
| run(wscript, ["//B", "//NoLogo", safePath(launcherPath)], { | ||
| stdio: "ignore", | ||
| windowsHide: true, | ||
| timeout: 15_000, | ||
| }); | ||
| } | ||
|
|
||
| function spawnTray(state: WindowsTrayEntry): void { | ||
| const launcher = installedTrayLauncherPath(); | ||
| if (existsSync(launcher)) { | ||
| launchInstalledWindowsTray(launcher); | ||
|
Comment on lines
+564
to
+566
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an installed Bun, CLI, or home path contains a literal environment-variable token such as Useful? React with 👍 / 👎. |
||
| return; | ||
| } | ||
| launchWindowsTrayHost(state); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Do not discard a stop request during startup.
The
-Mode Stoppath does not acquire$mutex. It can set$stopEventafter mutex acquisition but before thisReset()call.Reset()then clears the new request, and the tray ignores the stop command.Serialize the startup reset and stop-event
Set()operation with a shared gate, or use a startup handshake that distinguishes stale signals from new requests. The assertion intests/windows-tray.test.ts, Lines 329-380, checks ordering but not this interleaving.🤖 Prompt for AI Agents