diff --git a/scripts/package.mjs b/scripts/package.mjs index 6a48e7b..438166d 100644 --- a/scripts/package.mjs +++ b/scripts/package.mjs @@ -49,7 +49,13 @@ async function verifyLaunch(executable, label) { const child = spawn(executable, [`--user-data-dir=${userData}`], { cwd: path.dirname(executable), stdio: "ignore", - windowsHide: false + windowsHide: false, + env: { + ...process.env, + RPA_SKIP_SINGLE_INSTANCE: "1", + RPA_E2E: "1", + RPA_FIXTURE_PORT: String(18000 + Math.floor(Math.random() * 1000)) + } }); await delay(8000); const exited = child.exitCode !== null || child.signalCode !== null; diff --git a/scripts/spawn-test.mjs b/scripts/spawn-test.mjs new file mode 100644 index 0000000..190556d --- /dev/null +++ b/scripts/spawn-test.mjs @@ -0,0 +1,40 @@ +import { spawn } from "node:child_process"; + +const executable = process.argv[2]; +if (!executable) { + console.error("usage: node scripts/spawn-test.mjs [...args]"); + process.exit(2); +} +const env = { ...process.env }; +delete env.ELECTRON_RUN_AS_NODE; + +const child = spawn(executable, process.argv.slice(3), { + env, + stdio: ["ignore", "pipe", "pipe"], + windowsHide: false +}); + +child.stdout.on("data", (data) => process.stdout.write(`[out] ${data}`)); +child.stderr.on("data", (data) => process.stderr.write(`[err] ${data}`)); + +const timer = setTimeout(() => { + console.log(`STILL_RUNNING pid=${child.pid}`); + try { + child.kill("SIGKILL"); + } catch { + // ignore + } + setTimeout(() => process.exit(0), 1000); +}, 9000); + +child.on("exit", (code, signal) => { + clearTimeout(timer); + console.log(`EXIT code=${code} signal=${signal}`); + process.exit(0); +}); + +child.on("error", (error) => { + clearTimeout(timer); + console.error(`SPAWN_ERROR ${error.message}`); + process.exit(1); +}); diff --git a/src/main/index.ts b/src/main/index.ts index bfa11e6..77fda1c 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -172,7 +172,8 @@ function registerIpc(): void { }); } -const gotLock = app.requestSingleInstanceLock(); +// 打包冒烟/自动化测试需要与用户日常实例隔离;正常启动仍然保持单实例。 +const gotLock = process.env.RPA_SKIP_SINGLE_INSTANCE === "1" ? true : app.requestSingleInstanceLock(); if (!gotLock) { app.quit(); } else {