diff --git a/src/SyncTrayzor.sln b/src/SyncTrayzor.sln index 62cfda8a..0e1f0ad8 100644 --- a/src/SyncTrayzor.sln +++ b/src/SyncTrayzor.sln @@ -13,9 +13,10 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Debug|x64.ActiveCfg = Debug|x86 - {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Debug|x64.Build.0 = Debug|x86 - {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Debug|x86.ActiveCfg = Debug|x64 + {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Debug|x64.ActiveCfg = Debug|x64 + {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Debug|x64.Build.0 = Debug|x64 + {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Debug|x86.ActiveCfg = Debug|x86 + {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Debug|x86.Build.0 = Debug|x86 {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Release|x64.ActiveCfg = Release|x64 {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Release|x64.Build.0 = Release|x64 {D1F89B3D-7967-4DC6-AE45-50A7817FE54F}.Release|x86.ActiveCfg = Release|x64 diff --git a/src/SyncTrayzor/Bootstrapper.cs b/src/SyncTrayzor/Bootstrapper.cs index 471f9f67..6fce2be6 100644 --- a/src/SyncTrayzor/Bootstrapper.cs +++ b/src/SyncTrayzor/Bootstrapper.cs @@ -21,7 +21,7 @@ protected override void ConfigureIoC(IStyletIoCBuilder builder) { builder.Bind().ToInstance(new ApplicationState(this.Application)); builder.Bind().To().InSingletonScope(); - builder.Bind().ToSelf().InSingletonScope(); + builder.Bind().To().InSingletonScope(); builder.Bind().ToSelf().InSingletonScope(); builder.Bind().To().InSingletonScope(); builder.Bind().To().InSingletonScope(); diff --git a/src/SyncTrayzor/Pages/SettingsView.xaml b/src/SyncTrayzor/Pages/SettingsView.xaml index a1807759..82c8747a 100644 --- a/src/SyncTrayzor/Pages/SettingsView.xaml +++ b/src/SyncTrayzor/Pages/SettingsView.xaml @@ -7,15 +7,16 @@ xmlns:pages="clr-namespace:SyncTrayzor.Pages" mc:Ignorable="d" d:DataContext="{d:DesignInstance pages:SettingsViewModel}" - Title="SettingsView" Height="500" Width="300" + Title="SettingsView" Height="500" Width="400" ResizeMode="NoResize" SizeToContent="Height"> - + @@ -37,10 +38,18 @@ - + - Automatically start on login - + + Permission denied. Please start SyncTrayzor as an Administrator to change these settings. + + + Automatically start on login + + Start Minimized @@ -48,7 +57,7 @@ - + Folders unavailable. Please start Syncthing diff --git a/src/SyncTrayzor/Pages/SettingsViewModel.cs b/src/SyncTrayzor/Pages/SettingsViewModel.cs index 36dfb202..68955481 100644 --- a/src/SyncTrayzor/Pages/SettingsViewModel.cs +++ b/src/SyncTrayzor/Pages/SettingsViewModel.cs @@ -25,11 +25,27 @@ public class SettingsViewModel : Screen public bool StartSyncThingAutomatically { get; set; } public string SyncThingAddress { get; set; } public string SyncThingApiKey { get; set; } + + public bool CanReadAutostart { get; set; } + public bool CanWriteAutostart { get; set; } + public bool CanReadOrWriteAutostart + { + get { return this.CanReadAutostart || this.CanWriteAutostart; } + } + public bool CanReadAndWriteAutostart + { + get { return this.CanReadAutostart && this.CanWriteAutostart; } + } public bool StartOnLogon { get; set; } public bool StartMinimized { get; set; } + public bool StartMinimizedEnabled + { + get { return this.CanReadAndWriteAutostart && this.StartOnLogon; } + } + public BindableCollection WatchedFolders { get; set; } - public SettingsViewModel(IConfigurationProvider configurationProvider) + public SettingsViewModel(IConfigurationProvider configurationProvider, IAutostartProvider autostartProvider) { this.DisplayName = "Settings"; @@ -50,6 +66,9 @@ public SettingsViewModel(IConfigurationProvider configurationProvider) Folder = x.ID, IsSelected = x.IsWatched })); + + this.CanReadAutostart = autostartProvider.CanRead; + this.CanWriteAutostart = autostartProvider.CanWrite; } public void Save() diff --git a/src/SyncTrayzor/Services/AutostartProvider.cs b/src/SyncTrayzor/Services/AutostartProvider.cs index 9f0296a3..04ebe8d7 100644 --- a/src/SyncTrayzor/Services/AutostartProvider.cs +++ b/src/SyncTrayzor/Services/AutostartProvider.cs @@ -3,39 +3,77 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Security; using System.Text; using System.Threading.Tasks; using System.Windows; namespace SyncTrayzor.Services { + public interface IAutostartProvider + { + bool CanRead { get; } + bool CanWrite { get; } + + AutostartConfiguration GetCurrentSetup(); + void SetAutoStart(AutostartConfiguration config); + } + public class AutostartConfiguration { public bool AutoStart { get; set; } public bool StartMinimized { get; set; } } - public class AutostartProvider + public class AutostartProvider : IAutostartProvider { private const string applicationName = "SyncTrayzor"; - private RegistryKey OpenRegistryKey() + public bool CanRead { get; private set; } + public bool CanWrite { get; private set; } + + public AutostartProvider() { - return Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true); + // Check our access + try + { + this.OpenRegistryKey(true).Dispose(); + this.CanWrite = true; + this.CanRead = true; + return; + } + catch (SecurityException) { } + + try + { + this.OpenRegistryKey(false).Dispose(); + this.CanRead = true; + } + catch (SecurityException) { } + } + + private RegistryKey OpenRegistryKey(bool writable) + { + return Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", writable); } public AutostartConfiguration GetCurrentSetup() { + if (!this.CanRead) + throw new InvalidOperationException("Don't have permission to read the registry"); + bool autoStart = false; bool startMinimized = false; - var registryKey = this.OpenRegistryKey(); - var value = registryKey.GetValue(applicationName) as string; - if (value != null) + using (var registryKey = this.OpenRegistryKey(false)) { - autoStart = true; - if (value.Contains(" -minimized")) - startMinimized = true; + var value = registryKey.GetValue(applicationName) as string; + if (value != null) + { + autoStart = true; + if (value.Contains(" -minimized")) + startMinimized = true; + } } return new AutostartConfiguration() { AutoStart = autoStart, StartMinimized = startMinimized }; @@ -43,17 +81,22 @@ public AutostartConfiguration GetCurrentSetup() public void SetAutoStart(AutostartConfiguration config) { - var registryKey = this.OpenRegistryKey(); - var keyExists = registryKey.GetValue(applicationName) != null; + if (!this.CanWrite) + throw new InvalidOperationException("Don't have permission to write to the registry"); - if (config.AutoStart) - { - var path = String.Format("\"{0}\"{1}", Assembly.GetExecutingAssembly().Location, config.StartMinimized ? " -minimized" : ""); - registryKey.SetValue(applicationName, path); - } - else if (keyExists) + using (var registryKey = this.OpenRegistryKey(true)) { - registryKey.DeleteValue(applicationName); + var keyExists = registryKey.GetValue(applicationName) != null; + + if (config.AutoStart) + { + var path = String.Format("\"{0}\"{1}", Assembly.GetExecutingAssembly().Location, config.StartMinimized ? " -minimized" : ""); + registryKey.SetValue(applicationName, path); + } + else if (keyExists) + { + registryKey.DeleteValue(applicationName); + } } } } diff --git a/src/SyncTrayzor/Services/ConfigurationApplicator.cs b/src/SyncTrayzor/Services/ConfigurationApplicator.cs index 8806488e..550705c5 100644 --- a/src/SyncTrayzor/Services/ConfigurationApplicator.cs +++ b/src/SyncTrayzor/Services/ConfigurationApplicator.cs @@ -16,7 +16,7 @@ public class ConfigurationApplicator private readonly INotifyIconManager notifyIconManager; private readonly ISyncThingManager syncThingManager; - private readonly AutostartProvider autostartProvider; + private readonly IAutostartProvider autostartProvider; private readonly IWatchedFolderMonitor watchedFolderMonitor; private readonly IGithubApiClient githubApiClient; private readonly IUpdateChecker updateChecker; @@ -25,7 +25,7 @@ public ConfigurationApplicator( IConfigurationProvider configurationProvider, INotifyIconManager notifyIconManager, ISyncThingManager syncThingManager, - AutostartProvider autostartProvider, + IAutostartProvider autostartProvider, IWatchedFolderMonitor watchedFolderMonitor, IGithubApiClient githubApiClient, IUpdateChecker updateChecker) @@ -61,6 +61,10 @@ private void UpdateConfigOnInit() private void UpdateAutostart() { + // Don't have permission? Meh + if (!this.autostartProvider.CanRead) + return; + // If the user's manually updated the registry themselves, update our config to match var config = this.configurationProvider.Load(); var autostartConfig = this.autostartProvider.GetCurrentSetup(); @@ -90,7 +94,9 @@ private void ApplyNewConfiguration(Configuration configuration) this.syncThingManager.ExecutablePath = configuration.SyncthingPath; this.syncThingManager.ApiKey = configuration.SyncthingApiKey; - this.autostartProvider.SetAutoStart(new AutostartConfiguration() { AutoStart = configuration.StartOnLogon, StartMinimized = configuration.StartMinimized }); + // Don't have permission? Meh + if (this.autostartProvider.CanWrite) + this.autostartProvider.SetAutoStart(new AutostartConfiguration() { AutoStart = configuration.StartOnLogon, StartMinimized = configuration.StartMinimized }); this.watchedFolderMonitor.WatchedFolderIDs = configuration.Folders.Where(x => x.IsWatched).Select(x => x.ID);