Windows system utilities like ipconfig, systeminfo, etc. write directly to the console via WriteConsole API instead of stdout. When Node.js spawns cmd.exe with piped stdio, these utilities produce empty output. Changes: - Switch from cmd.exe to PowerShell on Windows (properly redirects output) - Disable detached mode on Windows (PowerShell doesn't pipe stdout when detached) - Add windowsHide option to prevent console window flashing - Update tests to use PowerShell-compatible syntax (Start-Sleep, semicolons)
60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
import { spawn } from "node:child_process";
|
|
|
|
export function getShellConfig(): { shell: string; args: string[] } {
|
|
if (process.platform === "win32") {
|
|
// Use PowerShell instead of cmd.exe on Windows.
|
|
// Problem: Many Windows system utilities (ipconfig, systeminfo, etc.) write
|
|
// directly to the console via WriteConsole API, bypassing stdout pipes.
|
|
// When Node.js spawns cmd.exe with piped stdio, these utilities produce no output.
|
|
// PowerShell properly captures and redirects their output to stdout.
|
|
return {
|
|
shell: "powershell.exe",
|
|
args: ["-NoProfile", "-NonInteractive", "-Command"],
|
|
};
|
|
}
|
|
|
|
const shell = process.env.SHELL?.trim() || "sh";
|
|
return { shell, args: ["-c"] };
|
|
}
|
|
|
|
export function sanitizeBinaryOutput(text: string): string {
|
|
const scrubbed = text.replace(/[\p{Format}\p{Surrogate}]/gu, "");
|
|
if (!scrubbed) return scrubbed;
|
|
const chunks: string[] = [];
|
|
for (const char of scrubbed) {
|
|
const code = char.codePointAt(0);
|
|
if (code == null) continue;
|
|
if (code === 0x09 || code === 0x0a || code === 0x0d) {
|
|
chunks.push(char);
|
|
continue;
|
|
}
|
|
if (code < 0x20) continue;
|
|
chunks.push(char);
|
|
}
|
|
return chunks.join("");
|
|
}
|
|
|
|
export function killProcessTree(pid: number): void {
|
|
if (process.platform === "win32") {
|
|
try {
|
|
spawn("taskkill", ["/F", "/T", "/PID", String(pid)], {
|
|
stdio: "ignore",
|
|
detached: true,
|
|
});
|
|
} catch {
|
|
// ignore errors if taskkill fails
|
|
}
|
|
return;
|
|
}
|
|
|
|
try {
|
|
process.kill(-pid, "SIGKILL");
|
|
} catch {
|
|
try {
|
|
process.kill(pid, "SIGKILL");
|
|
} catch {
|
|
// process already dead
|
|
}
|
|
}
|
|
}
|