diff --git a/update.py b/update.py index 3171147..2ca2e79 100644 --- a/update.py +++ b/update.py @@ -37,10 +37,15 @@ def run(cmd, **kw): def ps(script): - """Run a PowerShell snippet, return (rc, stdout).""" + """Run a PowerShell snippet, return (rc, stdout+stderr).""" r = subprocess.run(["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", script], cwd=HERE, capture_output=True, text=True) - return r.returncode, (r.stdout or "").strip() + return r.returncode, ((r.stdout or "") + (r.stderr or "")).strip() + + +def pythonw(): + p = os.path.join(os.path.dirname(sys.executable), "pythonw.exe") + return p if os.path.exists(p) else "pythonw.exe" def ensure_config(): @@ -116,38 +121,44 @@ def start_watchers(cfg_path): " (drag a box around the Ore Hold fill bar; saved forever after.)") -def ensure_task(): - """Register a daily + at-logon Scheduled Task so this runs itself forever. - Idempotent: only creates it if missing.""" +def ensure_logon_autostart(): + """Drop a launcher in the Startup folder so this runs at every logon. + No admin needed — most reliable auto-start mechanism on Windows.""" + if not WIN: + return False + rc, startup = ps("[Environment]::GetFolderPath('Startup')") + startup = startup.strip() + if rc != 0 or not startup or not os.path.isdir(startup): + print("! couldn't find Startup folder for logon auto-start") + return False + launcher = os.path.join(startup, "EveWatcher.cmd") + body = ('@echo off\r\n' + f'start "" "{pythonw()}" "{os.path.join(HERE, "update.py")}"\r\n') + with open(launcher, "w", newline="") as f: + f.write(body) + print(f"• logon auto-start installed: {launcher}") + return True + + +def ensure_daily_task(): + """Best-effort daily Scheduled Task (covers PCs left on for days). Uses + schtasks (works for the current user without admin). Idempotent.""" if not WIN: return - rc, _ = ps(f"Get-ScheduledTask -TaskName '{TASK}' -ErrorAction SilentlyContinue") - if rc == 0: - print(f"• Scheduled Task '{TASK}' already set (auto-update at logon + daily).") + q = subprocess.run(["schtasks", "/query", "/tn", TASK], + capture_output=True, text=True) + if q.returncode == 0: + print(f"• daily task '{TASK}' already set.") return - pyw = os.path.join(os.path.dirname(sys.executable), "pythonw.exe") - if not os.path.exists(pyw): - pyw = "pythonw.exe" - here = HERE.replace("'", "''") - pyw_e = pyw.replace("'", "''") - snippet = ( - f"$a = New-ScheduledTaskAction -Execute '{pyw_e}' " - f"-Argument '\"{here}\\update.py\"' -WorkingDirectory '{here}';" - "$t1 = New-ScheduledTaskTrigger -AtLogOn;" - "$t2 = New-ScheduledTaskTrigger -Daily -At 5am;" - "$s = New-ScheduledTaskSettingsSet -StartWhenAvailable " - "-AllowStartIfOnBatteries -DontStopIfGoingOnBatteries " - "-ExecutionTimeLimit (New-TimeSpan -Hours 1);" - "$p = New-ScheduledTaskPrincipal -UserId $env:USERNAME " - "-LogonType Interactive -RunLevel Limited;" - f"Register-ScheduledTask -TaskName '{TASK}' -Action $a -Trigger $t1,$t2 " - "-Settings $s -Principal $p -Force | Out-Null") - rc, out = ps(snippet) - if rc == 0: - print(f"• Scheduled Task '{TASK}' created — auto-updates at logon + daily 5am. " - "You never have to run this again.") + tr = f'"{pythonw()}" "{os.path.join(HERE, "update.py")}"' + c = subprocess.run(["schtasks", "/create", "/tn", TASK, "/tr", tr, + "/sc", "DAILY", "/st", "05:00", "/f"], + capture_output=True, text=True) + if c.returncode == 0: + print(f"• daily auto-update task '{TASK}' created (05:00).") else: - print(f"! couldn't register Scheduled Task: {out}") + print(f"• daily task not created ({(c.stdout + c.stderr).strip() or 'unknown'});" + " logon auto-start still covers updates.") def main(): @@ -160,7 +171,8 @@ def main(): start_watchers(cfg) else: print("• up to date and watchers already running — nothing to restart.") - ensure_task() + ensure_logon_autostart() + ensure_daily_task() print("\nDone. Hands-off from here: it updates + keeps itself running automatically.")