cicy-desktop 2.1.104 → 2.1.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cicy-desktop",
3
- "version": "2.1.104",
3
+ "version": "2.1.105",
4
4
  "description": "CiCy - AI-powered operating system browser",
5
5
  "main": "src/main.js",
6
6
  "bin": {
@@ -428,36 +428,54 @@ async function installDocker({ emit, dest } = {}) {
428
428
  await launchElevated(target, ["install", "--quiet", "--accept-license"], { emit: e });
429
429
  }
430
430
 
431
- // Run an admin-manifest exe (Docker Desktop Installer) ELEVATED. A plain
432
- // child_process.spawn of a requireAdministrator exe from a non-elevated process
433
- // fails with ERROR_ELEVATION_REQUIRED (740) and never shows UAC which is why
434
- // the installer "downloaded but didn't auto-install". ShellExecute with the
435
- // "runas" verb is the only way to raise the UAC prompt + elevate. We drive it
436
- // via VBScript/cscript because PowerShell is blocked by 360 on these machines.
437
- // ShellExecute returns immediately (installer runs in the background); bootstrap
438
- // then polls dockerOk(). Falls back to a direct spawn if cscript is unavailable.
439
- function launchElevated(exe, args, { emit } = {}) {
431
+ // Run an admin-manifest exe (the Docker Desktop installer) ELEVATED + in the
432
+ // user's INTERACTIVE session so its GUI is visible. A plain spawn fails (740,
433
+ // no UAC). The reliable method on these machines (verified) is a one-shot
434
+ // scheduled task with /rl HIGHEST /it: it runs with the built-in Administrator's
435
+ // elevated token (no UAC prompt) in the logged-on session, and unlike
436
+ // cscript/VBS ShellExecute "runas" isn't blocked by 360. cscript is kept only
437
+ // as a last-ditch fallback.
438
+ function elevateViaTask(exe, args) {
440
439
  return new Promise((resolve) => {
440
+ try {
441
+ const user = process.env["USERNAME"] || "Administrator";
442
+ const stamp = `${process.pid}${Math.floor(Math.random() * 1e6)}`;
443
+ const tn = `cicy-elevate-${stamp}`;
444
+ // A wrapper .cmd in a no-space temp path avoids schtasks /tr quoting hell;
445
+ // the .cmd itself quotes the (space-containing) exe path.
446
+ const cmdPath = path.join(os.tmpdir(), `${tn}.cmd`);
447
+ const line = `"${exe}"` + (args.length ? " " + args.map((a) => (/\s/.test(a) ? `"${a}"` : a)).join(" ") : "");
448
+ fs.writeFileSync(cmdPath, `@echo off\r\n${line}\r\n`, "utf8");
449
+ const sch = (a, cb) => execFile("schtasks", a, { windowsHide: true }, cb);
450
+ sch(["/create", "/tn", tn, "/tr", cmdPath, "/sc", "ONCE", "/st", "00:00", "/rl", "HIGHEST", "/ru", user, "/it", "/f"], (err) => {
451
+ if (err) return resolve(false);
452
+ sch(["/run", "/tn", tn], (rerr) => {
453
+ // clean the task + wrapper after a delay (installer keeps running).
454
+ setTimeout(() => { sch(["/delete", "/tn", tn, "/f"], () => {}); try { fs.unlinkSync(cmdPath); } catch {} }, 30000);
455
+ resolve(!rerr);
456
+ });
457
+ });
458
+ } catch { resolve(false); }
459
+ });
460
+ }
461
+
462
+ function launchElevated(exe, args, { emit } = {}) {
463
+ return new Promise(async (resolve) => {
464
+ // 1) Preferred: scheduled task /rl HIGHEST (elevated, interactive, 360-safe).
465
+ if (await elevateViaTask(exe, args)) return resolve(true);
466
+ // 2) Fallback: cscript/VBS ShellExecute "runas" (shows a UAC prompt).
441
467
  try {
442
468
  const vbs = path.join(os.tmpdir(), "cicy-docker-elevate.vbs");
443
469
  const argStr = args.join(" ").replace(/"/g, '""');
444
470
  const exeEsc = String(exe).replace(/"/g, '""');
445
- // chr(34) = a literal double-quote inside the VBS string literals.
446
- fs.writeFileSync(vbs,
447
- `Set s = CreateObject("Shell.Application")\r\n` +
448
- `s.ShellExecute "${exeEsc}", "${argStr}", "", "runas", 1\r\n`,
449
- "utf8");
471
+ fs.writeFileSync(vbs, `Set s = CreateObject("Shell.Application")\r\ns.ShellExecute "${exeEsc}", "${argStr}", "", "runas", 1\r\n`, "utf8");
450
472
  const child = spawn("cscript", ["//nologo", vbs], { windowsHide: true, detached: true, stdio: "ignore" });
451
- let done = false;
452
- const fin = (ok) => { if (done) return; done = true; resolve(ok); };
473
+ let done = false; const fin = (ok) => { if (!done) { done = true; resolve(ok); } };
453
474
  child.on("error", () => {
454
- // cscript missing/blocked → best-effort direct spawn (works if elevated).
455
475
  try {
456
- emit && emit({ phase: "install-docker", status: "running", message: "提权脚本不可用,尝试直接启动安装包…" });
476
+ emit && emit({ phase: "install-docker", status: "running", message: "提权方式受限,尝试直接启动安装包…" });
457
477
  const c2 = spawn(exe, args, { windowsHide: false, detached: true, stdio: "ignore" });
458
- c2.on("error", () => fin(false));
459
- c2.on("spawn", () => fin(true));
460
- c2.on("exit", () => fin(true));
478
+ c2.on("error", () => fin(false)); c2.on("spawn", () => fin(true)); c2.on("exit", () => fin(true));
461
479
  } catch { fin(false); }
462
480
  });
463
481
  child.on("exit", () => fin(true));