Spaces:
Paused
Paused
| import { execFile, spawn } from "child_process"; | |
| export function getErrorMessage(error: unknown): string { | |
| return error instanceof Error ? error.message : String(error); | |
| } | |
| export function execFileText(command: string, args: string[]): Promise<string> { | |
| return new Promise((resolve, reject) => { | |
| execFile(command, args, { encoding: "utf8" }, (error, stdout, stderr) => { | |
| if (error) { | |
| reject(new Error(`Command failed: ${getErrorMessage(error)}\n${stderr}`)); | |
| return; | |
| } | |
| resolve(stdout); | |
| }); | |
| }); | |
| } | |
| export function execFileWithPassword( | |
| command: string, | |
| args: string[], | |
| password: string, | |
| stdinAfterPassword = "" | |
| ): Promise<string> { | |
| return new Promise((resolve, reject) => { | |
| const child = spawn(command, args, { | |
| stdio: ["pipe", "pipe", "pipe"], | |
| }); | |
| let stdout = ""; | |
| let stderr = ""; | |
| let settled = false; | |
| const settle = (error: Error | null) => { | |
| if (settled) return; | |
| settled = true; | |
| if (error) { | |
| reject(error); | |
| return; | |
| } | |
| resolve(stdout); | |
| }; | |
| child.stdout?.on("data", (chunk) => { | |
| stdout += chunk.toString(); | |
| }); | |
| child.stderr?.on("data", (chunk) => { | |
| stderr += chunk.toString(); | |
| }); | |
| child.on("error", (error) => { | |
| settle(new Error(`Command failed: ${getErrorMessage(error)}\n${stderr}`)); | |
| }); | |
| child.on("close", (code) => { | |
| if (code === 0) { | |
| settle(null); | |
| return; | |
| } | |
| settle(new Error(`Command failed with code ${code}\n${stderr}`)); | |
| }); | |
| child.stdin?.write(`${password}\n${stdinAfterPassword}`); | |
| child.stdin?.end(); | |
| }); | |
| } | |
| export function quotePowerShell(value: string): string { | |
| return `'${value.replace(/'/g, "''")}'`; | |
| } | |
| export function runPowerShell(script: string): Promise<string> { | |
| return execFileText("powershell", [ | |
| "-NoProfile", | |
| "-NonInteractive", | |
| "-ExecutionPolicy", | |
| "Bypass", | |
| "-Command", | |
| script, | |
| ]); | |
| } | |
| export function runElevatedPowerShell(script: string): Promise<string> { | |
| const encoded = Buffer.from(script, "utf16le").toString("base64"); | |
| const wrapper = ` | |
| $proc = Start-Process powershell -ArgumentList @( | |
| '-NoProfile', | |
| '-NonInteractive', | |
| '-ExecutionPolicy', | |
| 'Bypass', | |
| '-EncodedCommand', | |
| '${encoded}' | |
| ) -Verb RunAs -Wait -PassThru; | |
| if ($proc.ExitCode -ne 0) { | |
| throw "Elevated command exited with code $($proc.ExitCode)" | |
| } | |
| `; | |
| return runPowerShell(wrapper); | |
| } | |