import { execFile } from 'child_process'; import * as path from 'path'; import { promisify } from 'util'; const execFileAsync = promisify(execFile); const MAX_PROCESS_NAMES = 512; export async function listRunningProcessNames(): Promise { if (process.platform === 'win32') { return normalizeProcessNames(await listWindowsProcessNames()); } if (process.platform === 'linux') { return normalizeProcessNames(await listLinuxProcessNames()); } return []; } async function listLinuxProcessNames(): Promise { const { stdout } = await execFileAsync('ps', ['-eo', 'comm='], { maxBuffer: 1024 * 1024, timeout: 5_000 }); return stdout.split('\n'); } async function listWindowsProcessNames(): Promise { const { stdout } = await execFileAsync('tasklist', [ '/FO', 'CSV', '/NH' ], { maxBuffer: 1024 * 1024, timeout: 5_000, windowsHide: true }); return stdout .split(/\r?\n/) .map((line) => parseCsvFirstColumn(line)); } function parseCsvFirstColumn(line: string): string { const trimmed = line.trim(); if (!trimmed) { return ''; } if (!trimmed.startsWith('"')) { return trimmed.split(',')[0] ?? ''; } const endQuoteIndex = trimmed.indexOf('"', 1); return endQuoteIndex > 1 ? trimmed.slice(1, endQuoteIndex) : ''; } function normalizeProcessNames(names: string[]): string[] { const normalized = new Set(); for (const rawName of names) { const name = normalizeProcessName(rawName); if (name) { normalized.add(name); } } return Array.from(normalized) .sort() .slice(0, MAX_PROCESS_NAMES); } function normalizeProcessName(rawName: string): string { const baseName = path.basename(rawName.trim()).trim(); if (!baseName || baseName.length > 96) { return ''; } return baseName; }