desktop open: a hidden tray copy that is already running counts once its window is visible (Windows), graceful stop wait 3 s on Windows
This commit is contained in:
parent
d4cf1ad3a1
commit
8df41a26b0
5 changed files with 58 additions and 17 deletions
|
|
@ -5,7 +5,7 @@
|
|||
import { posix } from 'node:path';
|
||||
import { compareVersions } from './desktop-install';
|
||||
|
||||
export interface Proc { pid: number; exe: string; args: string }
|
||||
export interface Proc { pid: number; exe: string; args: string; /** Windows only: the process has a visible top-level window. */ window?: boolean }
|
||||
|
||||
/** The executable a process of the installed app runs from (the .app bundle's binary on macOS). */
|
||||
export function appExe(platform: NodeJS.Platform, installedPath: string): string {
|
||||
|
|
@ -16,7 +16,7 @@ export function appExe(platform: NodeJS.Platform, installedPath: string): string
|
|||
export function listCommand(platform: NodeJS.Platform): string[] {
|
||||
if (platform === 'win32') {
|
||||
return ['powershell', '-NoProfile', '-NonInteractive', '-Command',
|
||||
"Get-CimInstance Win32_Process -Filter \"Name='storebound-desktop.exe'\" | Select-Object ProcessId,ExecutablePath,CommandLine | ConvertTo-Json -Compress"];
|
||||
"Get-CimInstance Win32_Process -Filter \"Name='storebound-desktop.exe'\" | ForEach-Object { $g = Get-Process -Id $_.ProcessId -ErrorAction SilentlyContinue; [pscustomobject]@{ ProcessId = $_.ProcessId; ExecutablePath = $_.ExecutablePath; CommandLine = $_.CommandLine; Window = [bool]($g -and $g.MainWindowHandle -ne 0) } } | ConvertTo-Json -Compress"];
|
||||
}
|
||||
return ['ps', '-axww', '-o', 'pid=,args='];
|
||||
}
|
||||
|
|
@ -28,8 +28,8 @@ export function parseProcs(platform: NodeJS.Platform, out: string): Proc[] {
|
|||
if (!t) return [];
|
||||
let j: unknown;
|
||||
try { j = JSON.parse(t); } catch { return []; }
|
||||
const rows = (Array.isArray(j) ? j : [j]) as { ProcessId?: number; ExecutablePath?: string | null; CommandLine?: string | null }[];
|
||||
return rows.filter(r => typeof r?.ProcessId === 'number').map(r => ({ pid: r.ProcessId!, exe: r.ExecutablePath ?? '', args: r.CommandLine ?? '' }));
|
||||
const rows = (Array.isArray(j) ? j : [j]) as { ProcessId?: number; ExecutablePath?: string | null; CommandLine?: string | null; Window?: boolean }[];
|
||||
return rows.filter(r => typeof r?.ProcessId === 'number').map(r => ({ pid: r.ProcessId!, exe: r.ExecutablePath ?? '', args: r.CommandLine ?? '', window: r.Window === true }));
|
||||
}
|
||||
const procs: Proc[] = [];
|
||||
for (const line of out.split('\n')) {
|
||||
|
|
@ -51,6 +51,20 @@ export function matchByPath(platform: NodeJS.Platform, procs: Proc[], exe: strin
|
|||
/** Was the process started hidden (the logon entry: tray only, no window)? */
|
||||
export const startedHidden = (p: Proc): boolean => /(?:^|\s|")--hidden(?:\s|"|$)/.test(p.args);
|
||||
|
||||
/** Is the app open for the user? Windows: a process of ours has a visible window (a running tray copy started with
|
||||
* --hidden counts once the single-instance handoff showed its window). Elsewhere a window cannot be seen from here:
|
||||
* a process started without --hidden, or a hidden copy that the new start handed over to (`handedOver`: the new
|
||||
* process exited normally), counts. 'none' = no process, 'hidden' = only tray copies and no visible window. */
|
||||
export function openState(platform: NodeJS.Platform, procs: Proc[], handedOver: boolean): 'ok' | 'none' | 'hidden' {
|
||||
if (!procs.length) return 'none';
|
||||
if (platform === 'win32') return procs.some(p => p.window) ? 'ok' : 'hidden';
|
||||
return procs.some(p => !startedHidden(p)) || handedOver ? 'ok' : 'hidden';
|
||||
}
|
||||
|
||||
/** Seconds to wait for a graceful quit before the forced stop: closing the window of a tray app only hides it, so on
|
||||
* Windows the graceful step is short. */
|
||||
export const graceMs = (platform: NodeJS.Platform): number => (platform === 'win32' ? 3_000 : 10_000);
|
||||
|
||||
/** The graceful stop (Windows: WM_CLOSE through taskkill without /F; elsewhere TERM) and the forced one, by PID. */
|
||||
export function stopCommand(platform: NodeJS.Platform, pid: number, force: boolean): string[] {
|
||||
if (platform === 'win32') return force ? ['taskkill', '/F', '/PID', String(pid)] : ['taskkill', '/PID', String(pid)];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue