From 33c8acc905e3cbcd76ded721b34ae2be790c1e9f Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 13:38:41 +0100 Subject: [PATCH 1/9] Check for updates on resume from sleep --- src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs b/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs index c520f635..9e897815 100644 --- a/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs +++ b/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs @@ -94,6 +94,7 @@ public UpdateManager( // We'll also check when the application is restored from tray this.applicationState.Startup += this.ApplicationStartup; + this.applicationState.ResumeFromSleep += this.ResumeFromSleep; this.applicationWindowState.RootWindowActivated += this.RootWindowActivated; } @@ -118,6 +119,12 @@ private async void ApplicationStartup(object sender, EventArgs e) await this.CheckForUpdatesAsync(); } + private async void ResumeFromSleep(object sender, EventArgs e) + { + if (this.UpdateCheckDue()) + await this.CheckForUpdatesAsync(); + } + private async void RootWindowActivated(object sender, ActivationEventArgs e) { if (this.toastCts != null) From f6b308926b02b13d91589f18592fd7283c75889b Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 15:46:49 +0100 Subject: [PATCH 2/9] Fix crash when 'Show tray icon only on close' is checked Fixes #45 --- src/SyncTrayzor/Bootstrapper.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SyncTrayzor/Bootstrapper.cs b/src/SyncTrayzor/Bootstrapper.cs index d632077f..eca6e224 100644 --- a/src/SyncTrayzor/Bootstrapper.cs +++ b/src/SyncTrayzor/Bootstrapper.cs @@ -102,6 +102,9 @@ protected override void Configure() autostartProvider.UpdatePathToSelf(); } + // Needs to be done before ConfigurationApplicator is run + this.Container.Get().Setup((ShellViewModel)this.RootViewModel); + this.Container.Get().ApplyConfiguration(); this.Container.Get().Enabled = true; @@ -118,7 +121,6 @@ protected override void Configure() { MessageBoxResult.Yes, Localizer.Translate("Generic_Dialog_Yes") }, }; - this.Container.Get().Setup((ShellViewModel)this.RootViewModel); this.Container.Get().ApplicationStarted(); } From ed624514db53edc602f98e4d1b57cae40783658e Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 16:00:42 +0100 Subject: [PATCH 3/9] Don't crash out if downloading the update fails --- .../UpdateManagement/UpdateDownloader.cs | 76 ++++++++++--------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/src/SyncTrayzor/Services/UpdateManagement/UpdateDownloader.cs b/src/SyncTrayzor/Services/UpdateManagement/UpdateDownloader.cs index 67b71475..706ee61a 100644 --- a/src/SyncTrayzor/Services/UpdateManagement/UpdateDownloader.cs +++ b/src/SyncTrayzor/Services/UpdateManagement/UpdateDownloader.cs @@ -36,50 +36,58 @@ public UpdateDownloader(IApplicationPathsProvider pathsProvider, IFilesystemProv public async Task DownloadUpdateAsync(string url, Version version) { - var downloadPath = Path.Combine(this.downloadsDir, String.Format(downloadFileName, version.ToString(3))); + try + { + var downloadPath = Path.Combine(this.downloadsDir, String.Format(downloadFileName, version.ToString(3))); - // Just in case... - this.filesystemProvider.CreateDirectory(this.downloadsDir); + // Just in case... + this.filesystemProvider.CreateDirectory(this.downloadsDir); - bool download = true; + bool download = true; - // Someone downloaded it already? Oh good. Let's see if it's corrupt or not... - if (this.filesystemProvider.Exists(downloadPath)) - { - logger.Info("Skipping download as file {0} already exists", downloadPath); - if (this.installerVerifier.Verify(downloadPath)) - { - download = false; - // Touch the file, so we (or someone else!) doesn't delete when cleaning up - this.filesystemProvider.SetLastAccessTimeUtc(downloadPath, DateTime.UtcNow); - } - else + // Someone downloaded it already? Oh good. Let's see if it's corrupt or not... + if (this.filesystemProvider.Exists(downloadPath)) { - logger.Info("Actually, it's corrupt. Re-downloading"); - this.filesystemProvider.Delete(downloadPath); + logger.Info("Skipping download as file {0} already exists", downloadPath); + if (this.installerVerifier.Verify(downloadPath)) + { + download = false; + // Touch the file, so we (or someone else!) doesn't delete when cleaning up + this.filesystemProvider.SetLastAccessTimeUtc(downloadPath, DateTime.UtcNow); + } + else + { + logger.Info("Actually, it's corrupt. Re-downloading"); + this.filesystemProvider.Delete(downloadPath); + } } - } - // House-keeping. Do this now, after SetLastAccessTimeUTc has been called, but before we start hitting the early-exits - this.CleanUpUnusedFiles(); - - if (download) - { - bool downloaded = await this.TryDownloadToFileAsync(downloadPath, url); - if (!downloaded) - return null; - - logger.Info("Verifying..."); + // House-keeping. Do this now, after SetLastAccessTimeUTc has been called, but before we start hitting the early-exits + this.CleanUpUnusedFiles(); - if (!this.installerVerifier.Verify(downloadPath)) + if (download) { - logger.Warn("Download verification failed. Deleting {0}", downloadPath); - this.filesystemProvider.Delete(downloadPath); - return null; + bool downloaded = await this.TryDownloadToFileAsync(downloadPath, url); + if (!downloaded) + return null; + + logger.Info("Verifying..."); + + if (!this.installerVerifier.Verify(downloadPath)) + { + logger.Warn("Download verification failed. Deleting {0}", downloadPath); + this.filesystemProvider.Delete(downloadPath); + return null; + } } - } - return downloadPath; + return downloadPath; + } + catch (Exception e) + { + logger.Error("Error in DownloadUpdateAsync", e); + return null; + } } private async Task TryDownloadToFileAsync(string downloadPath, string url) From 61c5b3e1ae3e069ab5f5ee53aabdf6fdd65487ca Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 16:01:32 +0100 Subject: [PATCH 4/9] Actually, make sure that if any part of the update mechanism crashes, we don't bring the application down --- src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs b/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs index 9e897815..639e89fd 100644 --- a/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs +++ b/src/SyncTrayzor/Services/UpdateManagement/UpdateManager.cs @@ -239,6 +239,10 @@ private async Task CheckForUpdatesAsync() break; } } + catch (Exception e) + { + logger.Error("Error in UpdateManager.CheckForUpdatesAsync", e); + } finally { this.versionCheckLock.Release(); From 09dd21c598e54ce7ae3c8d4fe1452aecaa148bb0 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 16:27:06 +0100 Subject: [PATCH 5/9] Work around 0.11 beta breaking the Version and LocalVersion fields Since we don't actually use these at the moment, just comment them out until it's clearer what they've changed to (dictionary? list?) Fixes #46 --- .../SyncThing/ApiClient/ItemStartedEvent.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/SyncTrayzor/SyncThing/ApiClient/ItemStartedEvent.cs b/src/SyncTrayzor/SyncThing/ApiClient/ItemStartedEvent.cs index b301712c..0c4aa38d 100644 --- a/src/SyncTrayzor/SyncThing/ApiClient/ItemStartedEvent.cs +++ b/src/SyncTrayzor/SyncThing/ApiClient/ItemStartedEvent.cs @@ -18,11 +18,15 @@ public class ItemStartedEventDetails [JsonProperty("Modified")] public long Modified { get; set; } // Is this supposed to be a DateTime? - [JsonProperty("Version")] - public long Version { get; set; } + // This changed in 0.11 beta, but it's not yet clear what do + // Since we don't use it anyway currently... + //[JsonProperty("Version")] + //public List Version { get; set; } - [JsonProperty("LocalVersion")] - public long LocalVersion { get; set; } + // This changed in 0.11 beta, but it's not yet clear what do + // Since we don't use it anyway currently... + //[JsonProperty("LocalVersion")] + //public List LocalVersion { get; set; } [JsonProperty("NumBlocks")] public long NumBlocks { get; set; } @@ -52,9 +56,8 @@ public override void Visit(IEventVisitor visitor) public override string ToString() { - return String.Format("", - this.Id, this.Time, this.Data.Item, this.Data.Folder, this.Data.Details.Name, this.Data.Details.Flags, this.Data.Details.Modified, - this.Data.Details.Version, this.Data.Details.LocalVersion, this.Data.Details.NumBlocks); + return String.Format("", + this.Id, this.Time, this.Data.Item, this.Data.Folder, this.Data.Details.Name, this.Data.Details.Flags, this.Data.Details.Modified, this.Data.Details.NumBlocks); } } } From 51878e0483008d394683c4360af86c21701b3573 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 16:50:53 +0100 Subject: [PATCH 6/9] Fix issue where SyncTrayzor would be started as admin after auto-upgrade --- installer/x64/installer-x64.iss | 2 +- installer/x86/installer-x86.iss | 2 +- src/InstallerRunner/Program.cs | 36 +++++++++++++++++-- .../Services/ProcessStartProvider.cs | 10 ++++-- .../InstalledUpdateVariantHandler.cs | 6 ++-- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/installer/x64/installer-x64.iss b/installer/x64/installer-x64.iss index 0d80b3fa..c048d6bf 100644 --- a/installer/x64/installer-x64.iss +++ b/installer/x64/installer-x64.iss @@ -74,7 +74,7 @@ Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Tasks: desk [Run] Filename: "{tmp}\dotNet451Setup.exe"; Parameters: "/passive /promptrestart"; Check: FrameworkIsNotInstalled; StatusMsg: "Microsoft .NET Framework 4.5.1 is being installed. Please wait..." -Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall +Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent [Code] function FrameworkIsNotInstalled: Boolean; diff --git a/installer/x86/installer-x86.iss b/installer/x86/installer-x86.iss index e67c9a4a..e8d04742 100644 --- a/installer/x86/installer-x86.iss +++ b/installer/x86/installer-x86.iss @@ -72,7 +72,7 @@ Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Tasks: desk [Run] Filename: "{tmp}\dotNet451Setup.exe"; Parameters: "/passive /promptrestart"; Check: FrameworkIsNotInstalled; StatusMsg: "Microsoft .NET Framework 4.5.1 is being installed. Please wait..." -Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall +Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent [Code] function FrameworkIsNotInstalled: Boolean; diff --git a/src/InstallerRunner/Program.cs b/src/InstallerRunner/Program.cs index 8747463c..235dd7c4 100644 --- a/src/InstallerRunner/Program.cs +++ b/src/InstallerRunner/Program.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -12,14 +13,39 @@ class Program { private const int ERROR_CANCELLED = 1223; - static int Main(string[] args) + static int Main(string[] argsIn) { - if (args.Length == 0) + var args = new List(argsIn); + + string launch = null; + var indexOfLaunch = args.IndexOf("-launch"); + if (indexOfLaunch > -1) + { + if (indexOfLaunch >= args.Count - 1) + { + Console.Error.WriteLine("Must provide an argument to -launch"); + return 1; + } + + launch = args[indexOfLaunch + 1]; + args.RemoveAt(indexOfLaunch + 1); + args.RemoveAt(indexOfLaunch); + } + + if (args.Count == 0) { Console.Error.WriteLine("Must provide at least one command-line argument"); return 1; } + if (!File.Exists(args[0])) + { + Console.Error.WriteLine("Could not find {0}", args[0]); + return 4; + } + + Console.WriteLine(String.Join(", ", args)); + var startInfo = new ProcessStartInfo() { FileName = args[0], @@ -30,7 +56,11 @@ static int Main(string[] args) try { - Process.Start(startInfo); + var process = Process.Start(startInfo); + process.WaitForExit(); + + if (!String.IsNullOrWhiteSpace(launch)) + Process.Start(launch); } catch (Win32Exception e) { diff --git a/src/SyncTrayzor/Services/ProcessStartProvider.cs b/src/SyncTrayzor/Services/ProcessStartProvider.cs index 17de0de3..39803e3e 100644 --- a/src/SyncTrayzor/Services/ProcessStartProvider.cs +++ b/src/SyncTrayzor/Services/ProcessStartProvider.cs @@ -14,7 +14,7 @@ public interface IProcessStartProvider void Start(string filename); void Start(string filename, string arguments); void StartDetached(string filename); - void StartElevatedDetached(string filename, string arguments); + void StartElevatedDetached(string filename, string arguments, string launchAfterFinished = null); } public class ProcessStartProvider : IProcessStartProvider @@ -50,8 +50,14 @@ public void StartDetached(string filename) Process.Start(startInfo); } - public void StartElevatedDetached(string filename, string arguments) + public void StartElevatedDetached(string filename, string arguments, string launchAfterFinished = null) { + if (arguments == null) + arguments = String.Empty; + + if (launchAfterFinished != null) + arguments += String.Format(" -launch \"{0}\"", launchAfterFinished); + var startInfo = new ProcessStartInfo() { FileName = Path.Combine(Path.GetDirectoryName(this.exeDir), installerRunner), diff --git a/src/SyncTrayzor/Services/UpdateManagement/InstalledUpdateVariantHandler.cs b/src/SyncTrayzor/Services/UpdateManagement/InstalledUpdateVariantHandler.cs index 6d2de71e..0cb71d16 100644 --- a/src/SyncTrayzor/Services/UpdateManagement/InstalledUpdateVariantHandler.cs +++ b/src/SyncTrayzor/Services/UpdateManagement/InstalledUpdateVariantHandler.cs @@ -10,16 +10,18 @@ public class InstalledUpdateVariantHandler : IUpdateVariantHandler { private readonly IUpdateDownloader updateDownloader; private readonly IProcessStartProvider processStartProvider; + private readonly IAssemblyProvider assemblyProvider; private string installerPath; public string VariantName { get { return "installed"; } } public bool CanAutoInstall { get; private set; } - public InstalledUpdateVariantHandler(IUpdateDownloader updateDownloader, IProcessStartProvider processStartProvider) + public InstalledUpdateVariantHandler(IUpdateDownloader updateDownloader, IProcessStartProvider processStartProvider, IAssemblyProvider assemblyProvider) { this.updateDownloader = updateDownloader; this.processStartProvider = processStartProvider; + this.assemblyProvider = assemblyProvider; } public async Task TryHandleUpdateAvailableAsync(VersionCheckResults checkResult) @@ -48,7 +50,7 @@ public void AutoInstall() if (this.installerPath == null) throw new InvalidOperationException("TryHandleUpdateAvailableAsync returned false: cannot call AutoInstall"); - this.processStartProvider.StartElevatedDetached(this.installerPath, "/SILENT"); + this.processStartProvider.StartElevatedDetached(this.installerPath, "/SILENT", this.assemblyProvider.Location); } } } From 2959cafe11a93f6bca6c016a3326849312c3c72c Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 15:51:14 +0100 Subject: [PATCH 7/9] Update changelog --- CHANGELOG.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ea68432c..1915333f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,14 @@ Changelog ========= +v1.0.13 +------- + + - Fix crash if 'Show tray icon only on close' is checked (#45) + - Fix undocumented REST API change in Syncthing 0.11 (#46) + - Check for updates on resume from sleep + - Ensure SyncTrayzor is started as original user after auto-update + v1.0.12 ------- From c9847c05487b8b381fcff9558a3c49a1c9c852b6 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 15:51:27 +0100 Subject: [PATCH 8/9] Bump version --- src/SyncTrayzor/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SyncTrayzor/Properties/AssemblyInfo.cs b/src/SyncTrayzor/Properties/AssemblyInfo.cs index 5e287865..676a6272 100644 --- a/src/SyncTrayzor/Properties/AssemblyInfo.cs +++ b/src/SyncTrayzor/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.12.0")] -[assembly: AssemblyFileVersion("1.0.12.0")] +[assembly: AssemblyVersion("1.0.13.0")] +[assembly: AssemblyFileVersion("1.0.13.0")] From 463ba990175e41700ddf8df23c4717c5cdca0cf4 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Mon, 13 Apr 2015 16:04:44 +0100 Subject: [PATCH 9/9] Update version_check.php --- server/version_check.php | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/server/version_check.php b/server/version_check.php index 6e17a856..ca37c444 100644 --- a/server/version_check.php +++ b/server/version_check.php @@ -48,6 +48,7 @@ set_error_handler('error_handler'); date_default_timezone_set('UCT'); +header('Content-Type: application/json'); function error_handler($severity, $message, $filename, $lineno) { @@ -64,20 +65,21 @@ function get_with_wildcard($src, $value, $default = null) } $versions = [ - // '1.0.12' => [ - // 'installed' => [ - // 'direct_download_url' => [ - // 'x64' => 'https://github.com/canton7/SyncTrayzor/releases/download/v1.0.11/SyncTrayzorSetup-x64.exe', - // 'x86' => 'https://github.com/canton7/SyncTrayzor/releases/download/v1.0.11/SyncTrayzorSetup-x86.exe' - // ], - // ], - // 'release_page_url' => 'https://github.com/canton7/SyncTrayzor/releases/tag/v1.0.11', - // 'release_notes' => "These\nare some release notes", - // ], + '1.0.13' => [ + // No direct_download_url, as it turns out the 1.0.12 auto-upgrader is a bit broken (will restart SyncTrayzor as admin) + // 'installed' => [ + // 'direct_download_url' => [ + // 'x64' => 'https://github.com/canton7/SyncTrayzor/releases/download/v1.0.13/SyncTrayzorSetup-x64.exe', + // 'x86' => 'https://github.com/canton7/SyncTrayzor/releases/download/v1.0.13/SyncTrayzorSetup-x86.exe' + // ], + // ], + 'release_page_url' => 'https://github.com/canton7/SyncTrayzor/releases/tag/v1.0.13', + 'release_notes' => "- Fix crash if 'Show tray icon only on close' is checked (#45)\n- Fix undocumented REST API change in Syncthing 0.11 (#46)\n- Check for updates on resume from sleep\n- Ensure SyncTrayzor is started as original user after auto-update", + ], ]; $upgrades = [ - // '1.0.11' => ['to' => '1.0.12', 'formatter' => '1'], + '1.0.12' => ['to' => '1.0.13', 'formatter' => '1'], ]; $response_formatters = [