fix(ariadne): Theseus on/off toggle never reached the tasks; updater read a stale manifest; uninstall left NRPT rules
Theseus (Settings › Plug-ins › Ariadne's Thread): - The elevated start/stop script was embedded in a double-quoted outer PowerShell string, so `$t` was interpolated away before the elevated shell saw it. It received `foreach ( in …)`, failed to parse, and the outer shell still exited 0 — "Turn on/off" reported success while doing nothing, in every shipped build. The script now goes across as -EncodedCommand. Off = Stop + Disable (the daemon task has an at-startup trigger, so a plain stop came back on reboot); on = Enable + Start. Exit 2 = daemon task missing, surfaced as a clear error. - Version/update check now reads dl.silentmode.st's releases manifest, the same one the Theseus updater uses. The silentmode.st copy lagged a day behind (still listing Theseus 0.3.31), so a new Ariadne release published to dl would not have been offered. - Install/update/uninstall now propagate the installer's exit code (-PassThru; exit $p.ExitCode) instead of always reading as success. Resolver package (needs a new installer build to reach users): - uninstall.ps1 removed only the ".bch" NRPT rule; install.ps1 adds one per advertised TLD. Sweep every "BNS .<tld> resolver" rule. Verified: daemon resolves BNS names and passes ICANN A/AAAA through when run unprivileged on port 15353; the encoded-command construction runs intact and propagates exit codes 0/2 in an unelevated reproduction.
This commit is contained in:
parent
56eff58fda
commit
c9dbcbde86
1 changed files with 43 additions and 7 deletions
50
main.js
50
main.js
|
|
@ -3797,7 +3797,11 @@ const ARIADNE_UNINSTALL_KEYS = [
|
|||
'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{7E7A5F1C-3B4E-4C8A-9E1D-ARIADNERSLVR}_is1',
|
||||
'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{7E7A5F1C-3B4E-4C8A-9E1D-ARIADNERSLVR}_is1',
|
||||
];
|
||||
const ARIADNE_MANIFEST_URL = "https://silentmode.st/releases-manifest.json";
|
||||
// Same manifest the Theseus updater reads (UPDATE_MANIFEST_URL). The copy on
|
||||
// silentmode.st is a mirror that has lagged behind dl.silentmode.st (2026-09-09:
|
||||
// it still listed Theseus 0.3.31 while dl had 0.3.44), so the Ariadne "Update"
|
||||
// button was checking against a stale version list.
|
||||
const ARIADNE_MANIFEST_URL = "https://dl.silentmode.st/releases-manifest.json";
|
||||
const ARIADNE_DL_ORIGIN = "https://dl.silentmode.st";
|
||||
const ARIADNE_MANIFEST_TTL_MS = 30 * 60 * 1000;
|
||||
let ariadneManifestCache = null; // { at:number, entry:{version,filename,sha256,url}|null }
|
||||
|
|
@ -3920,11 +3924,41 @@ function cmpVersions(a, b) {
|
|||
function ariadneSetState(on) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { spawn } = require("child_process");
|
||||
const verb = on ? "Start-ScheduledTask" : "Stop-ScheduledTask";
|
||||
const cmd = `foreach ($t in 'BNS Resolver Daemon','BNS Sia Bridge') { try { ${verb} -TaskName $t -ErrorAction Stop } catch {} }`;
|
||||
// Off = stop AND disable, on = enable AND start. The daemon task has an
|
||||
// at-startup trigger, so a plain Stop-ScheduledTask came back on the
|
||||
// next reboot and "Turn off" silently didn't stick.
|
||||
//
|
||||
// The inner script goes across as -EncodedCommand (base64 UTF-16LE). The
|
||||
// previous version embedded it in a double-quoted string on the OUTER
|
||||
// powershell's command line, which interpolated `$t` to nothing before
|
||||
// the elevated shell ever saw it — the elevated shell got
|
||||
// `foreach ( in ...)`, failed to parse, and the outer shell still exited
|
||||
// 0, so the toggle reported success while doing nothing.
|
||||
const inner = on
|
||||
? `$ok = $true
|
||||
foreach ($t in 'BNS Resolver Daemon','BNS Sia Bridge') {
|
||||
try { Enable-ScheduledTask -TaskName $t -ErrorAction Stop | Out-Null; Start-ScheduledTask -TaskName $t -ErrorAction Stop }
|
||||
catch { if ($t -eq 'BNS Resolver Daemon') { $ok = $false } }
|
||||
}
|
||||
if ($ok) { exit 0 } else { exit 2 }`
|
||||
: `$ok = $true
|
||||
foreach ($t in 'BNS Resolver Daemon','BNS Sia Bridge') {
|
||||
try { Stop-ScheduledTask -TaskName $t -ErrorAction Stop } catch {}
|
||||
try { Disable-ScheduledTask -TaskName $t -ErrorAction Stop | Out-Null }
|
||||
catch { if ($t -eq 'BNS Resolver Daemon') { $ok = $false } }
|
||||
}
|
||||
if ($ok) { exit 0 } else { exit 2 }`;
|
||||
const encoded = Buffer.from(inner, "utf16le").toString("base64");
|
||||
// -PassThru + exit $p.ExitCode: the elevated shell's exit code (0 ok,
|
||||
// 2 = daemon task missing) reaches us; a declined UAC prompt makes
|
||||
// Start-Process throw, which exits the outer shell non-zero.
|
||||
const ps = spawn("powershell.exe", ["-NoProfile", "-Command",
|
||||
"Start-Process powershell -Verb RunAs -Wait -WindowStyle Hidden -ArgumentList '-NoProfile','-Command',\"" + cmd.replace(/"/g, "`\"") + "\""], { windowsHide: true });
|
||||
ps.on("close", (code) => { if (code === 0) resolve(true); else reject(new Error("UAC declined or task failed (exit " + code + ")")); });
|
||||
`$p = Start-Process powershell -Verb RunAs -Wait -WindowStyle Hidden -PassThru -ArgumentList '-NoProfile','-NonInteractive','-EncodedCommand','${encoded}'; exit $p.ExitCode`], { windowsHide: true });
|
||||
ps.on("close", (code) => {
|
||||
if (code === 0) resolve(true);
|
||||
else if (code === 2) reject(new Error("the 'BNS Resolver Daemon' scheduled task is missing — reinstall Ariadne's Thread"));
|
||||
else reject(new Error("UAC declined or task failed (exit " + code + ")"));
|
||||
});
|
||||
ps.on("error", (e) => reject(e));
|
||||
});
|
||||
}
|
||||
|
|
@ -3938,8 +3972,10 @@ async function ariadneInstall() {
|
|||
const exePath = await ariadneDownloadInstaller(entry);
|
||||
const { spawn } = require("child_process");
|
||||
return new Promise((resolve, reject) => {
|
||||
// -PassThru + exit $p.ExitCode so Inno's own exit code reaches us; a bare
|
||||
// -Wait always returned 0 and a failed silent install looked like success.
|
||||
const ps = spawn("powershell.exe", ["-NoProfile", "-Command",
|
||||
`Start-Process -FilePath '${exePath.replace(/'/g, "''")}' -ArgumentList '/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART' -Verb RunAs -Wait`
|
||||
`$p = Start-Process -FilePath '${exePath.replace(/'/g, "''")}' -ArgumentList '/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART' -Verb RunAs -Wait -PassThru; exit $p.ExitCode`
|
||||
], { windowsHide: true });
|
||||
const cleanup = () => { try { fs.unlinkSync(exePath); } catch {} };
|
||||
ps.on("close", (code) => { cleanup(); code === 0 ? resolve(true) : reject(new Error("installer exited " + code)); });
|
||||
|
|
@ -3962,7 +3998,7 @@ function ariadneUninstall() {
|
|||
if (!uninstallCmd) return reject(new Error("Ariadne uninstaller not registered"));
|
||||
// uninstallCmd typically: "C:\Program Files (x86)\...\unins000.exe" /VERYSILENT
|
||||
// Spawn it elevated. Inno's silent uninstall respects /VERYSILENT so no UI.
|
||||
const runCmd = `Start-Process -FilePath 'cmd.exe' -ArgumentList '/c ${uninstallCmd.replace(/'/g, "''")} /SUPPRESSMSGBOXES /NORESTART' -Verb RunAs -Wait`;
|
||||
const runCmd = `$p = Start-Process -FilePath 'cmd.exe' -ArgumentList '/c ${uninstallCmd.replace(/'/g, "''")} /SUPPRESSMSGBOXES /NORESTART' -Verb RunAs -Wait -PassThru; exit $p.ExitCode`;
|
||||
const ps2 = spawn("powershell.exe", ["-NoProfile", "-Command", runCmd], { windowsHide: true });
|
||||
ps2.on("close", (code) => code === 0 ? resolve(true) : reject(new Error("uninstaller exited " + code)));
|
||||
ps2.on("error", reject);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue