From b05f8518a414d656b065f0f1cfdf1c018ca5cddf Mon Sep 17 00:00:00 2001 From: Andrew Szeto Date: Fri, 12 Jun 2026 22:17:52 -0700 Subject: [PATCH] fix(windows): create missing registry keys in enable On a fresh Windows install the Run key and the lazily created StartupApproved\Run key may not exist yet. enable() obtained each key through Registry.openPath, which throws when the key path is absent, and createValue (RegSetValueEx) only writes to an already-open handle without creating the key, so enable() threw on machines where these keys were missing. This switches enable() to Registry.currentUser.createKey, which creates the key and any missing parent keys along the path before writing, and opens an existing key unchanged. The registry paths are now constants shared with the read path. The read path and the value written for existing users are unchanged. --- lib/src/app_auto_launcher_impl_windows.dart | 24 ++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/src/app_auto_launcher_impl_windows.dart b/lib/src/app_auto_launcher_impl_windows.dart index a803fcb..9c267d7 100644 --- a/lib/src/app_auto_launcher_impl_windows.dart +++ b/lib/src/app_auto_launcher_impl_windows.dart @@ -23,16 +23,21 @@ class AppAutoLauncherImplWindows extends AppAutoLauncher { late String _registryValue; + static const String _runRegistryPath = + r'Software\Microsoft\Windows\CurrentVersion\Run'; + + static const String _startupApprovedRegistryPath = + r'Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run'; + RegistryKey get _regKey => Registry.openPath( RegistryHive.currentUser, - path: r'Software\Microsoft\Windows\CurrentVersion\Run', + path: _runRegistryPath, desiredAccessRights: AccessRights.allAccess, ); RegistryKey get _startupApprovedRegKey => Registry.openPath( RegistryHive.currentUser, - path: - r'Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run', + path: _startupApprovedRegistryPath, desiredAccessRights: AccessRights.allAccess, ); @@ -47,7 +52,13 @@ class AppAutoLauncherImplWindows extends AppAutoLauncher { @override Future enable() async { - _regKey.createValue( + // openPath (used on the read path) throws when a key does not exist, and + // createValue only writes to an already-open handle. On a fresh install + // the Run and StartupApproved\Run keys may not exist yet, so create them + // first. createKey creates any missing keys along the path and opens an + // existing key unchanged. + final regKey = Registry.currentUser.createKey(_runRegistryPath); + regKey.createValue( RegistryValue.string( appName, _registryValue, @@ -58,7 +69,10 @@ class AppAutoLauncherImplWindows extends AppAutoLauncher { // "2" as a first byte in this register means that the autostart is enabled bytes[0] = 2; - _startupApprovedRegKey.createValue(RegistryValue.binary(appName, bytes)); + final startupApprovedRegKey = Registry.currentUser.createKey( + _startupApprovedRegistryPath, + ); + startupApprovedRegKey.createValue(RegistryValue.binary(appName, bytes)); return true; }