Skip to content

feat(autolaunch): cross-platform auto-launch at user login#205

Draft
kdroidFilter wants to merge 1 commit intomainfrom
feat/autolaunch
Draft

feat(autolaunch): cross-platform auto-launch at user login#205
kdroidFilter wants to merge 1 commit intomainfrom
feat/autolaunch

Conversation

@kdroidFilter
Copy link
Copy Markdown
Owner

Summary

  • New autolaunch runtime module: unified API (AutoLaunch.state/enable/disable/wasStartedAtLogin/openSystemSettings) across packaging types.
  • MSIX backend: WinRT StartupTask API via WRL on a dedicated MTA thread (AWT EDT is STA, avoids message-pump-dependent async completion issues). TaskId auto-injected by the Gradle plugin when appx { addAutoLaunchExtension = true } (exposed via NucleusApp.startupTaskId).
  • Win32 (MSI/NSIS) backend: HKCU\...\Run + StartupApproved\Run parity rule (flag & 1 == 1DISABLED_BY_USER). Injects --nucleus-autostart CLI marker.
  • Auto-launch detection (AutoLaunch.wasStartedAtLogin(args)):
    • Win32: checks CLI marker.
    • MSIX: walks the process ancestor chain (skipping self-spawned jpackage launcher), detects sihost.exe as external parent (empirical finding on Win11 — MSIX startup activations are routed through Shell Infrastructure Host, not taskhostw.exe as some docs suggest). Deterministic, no heuristics, no WinAppSDK / PSF dependency.
  • Native DLLs: x64 + ARM64, ship in nucleus_autolaunch.dll. GraalVM reachability metadata included.
  • Gradle plugin: new AppXSettings.startupTaskId override, writes the resolved TaskId into nucleus-app.properties.
  • Example app: new Auto-Launch tab with toggle, diagnostic view, and home-screen banner when started at login.
  • Docs: new runtime/autolaunch.md page wired into mkdocs nav.
  • CI: build + verify + upload in build-natives.yaml; download + EXPECTED entries added to all 6 consumer workflows.

Test plan

  • Win32 (MSI or NSIS installer): enable via switch → logoff/logon → banner appears → disable via switch → logoff/logon → banner gone.
  • Win32: toggle off via Task Manager → state() reports DISABLED_BY_USERenable() returns BLOCKED_BY_USERopenSystemSettings() opens ms-settings:startupapps.
  • MSIX (AppX): install, toggle on, logoff/logon → isLaunchedByTaskScheduler diagnostic shows external parent = sihost.exe → banner visible.
  • MSIX manual launch (Start menu) → diagnostic shows external parent = explorer.exe → no banner.
  • MSIX StartupTaskState.DisabledByUser after user toggled via Task Manager → enable() returns BLOCKED_BY_USER (no re-enable attempt).
  • Silent app update: existing StartupApproved DISABLED_BY_USER not overwritten.
  • Tests: ./gradlew :autolaunch:test (Windows only).
  • GraalVM native image of the example still launches and detects auto-launch correctly.
  • macOS / Linux: all APIs return UNSUPPORTED / false, no crashes.

New autolaunch module with unified API across MSIX and Win32 packaging.
MSIX uses WinRT StartupTask; Win32 uses HKCU\Run + StartupApproved parity rule.
Detects auto-launched starts via CLI marker (Win32) and parent-process walk
to sihost.exe (MSIX). Plugin auto-injects StartupTask TaskId into app
metadata when addAutoLaunchExtension is enabled. Example gains an
Auto-Launch tab and home banner when started at login.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant