Refactor plugin architecture, isolate Windows-spefic code
This commit is contained in:
84
src/server/process/WindowsProcess.ts
Normal file
84
src/server/process/WindowsProcess.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { ChildProcess, spawn, SpawnOptions } from "child_process";
|
||||
import { OpenCodeProcess } from "./OpenCodeProcess";
|
||||
|
||||
export class WindowsProcess implements OpenCodeProcess {
|
||||
start(
|
||||
command: string,
|
||||
args: string[],
|
||||
options: SpawnOptions
|
||||
): ChildProcess {
|
||||
return spawn(command, args, {
|
||||
...options,
|
||||
shell: true,
|
||||
windowsHide: true,
|
||||
});
|
||||
}
|
||||
|
||||
async stop(process: ChildProcess): Promise<void> {
|
||||
const pid = process.pid;
|
||||
if (!pid) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[OpenCode] Stopping server process tree, PID:", pid);
|
||||
|
||||
// Use taskkill with /T flag to kill process tree
|
||||
await this.execAsync(`taskkill /T /F /PID ${pid}`);
|
||||
|
||||
// Wait for process to exit
|
||||
await this.waitForExit(process, 5000);
|
||||
}
|
||||
|
||||
async verifyCommand(command: string): Promise<string | null> {
|
||||
// Use 'where' command to check if executable exists in PATH
|
||||
try {
|
||||
await this.execAsync(`where "${command}"`);
|
||||
return null;
|
||||
} catch {
|
||||
return `Executable not found at '${command}'`;
|
||||
}
|
||||
}
|
||||
|
||||
private async waitForExit(
|
||||
process: ChildProcess,
|
||||
timeoutMs: number
|
||||
): Promise<void> {
|
||||
if (process.exitCode !== null || process.signalCode !== null) {
|
||||
return; // Already exited
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const timeout = setTimeout(() => {
|
||||
cleanup();
|
||||
resolve();
|
||||
}, timeoutMs);
|
||||
|
||||
const onExit = () => {
|
||||
cleanup();
|
||||
resolve();
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
clearTimeout(timeout);
|
||||
process.off("exit", onExit);
|
||||
process.off("error", onExit);
|
||||
};
|
||||
|
||||
process.once("exit", onExit);
|
||||
process.once("error", onExit);
|
||||
});
|
||||
}
|
||||
|
||||
private execAsync(command: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { exec } = require("child_process");
|
||||
exec(command, (error: Error | null) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user