/// <summary> /// Installes the available updates if there is an update available. /// </summary> /// <returns>Task.</returns> public async Task <SquirrelResult> InstallAvailableUpdatesAsync(SquirrelContext context) { Argument.IsNotNull(() => context); var result = new SquirrelResult { IsUpdateInstalledOrAvailable = false, CurrentVersion = GetCurrentApplicationVersion() }; var channelUrl = GetChannelUrl(context); if (string.IsNullOrWhiteSpace(channelUrl)) { return(result); } try { using (var mgr = new UpdateManager(channelUrl)) { Log.Info($"Checking for updates using url '{channelUrl}'"); var updateInfo = await mgr.CheckForUpdate(); if (updateInfo.ReleasesToApply.Count > 0) { Log.Info($"Found new version '{updateInfo.FutureReleaseEntry?.Version}' using url '{channelUrl}', installing update..."); result.IsUpdateInstalledOrAvailable = true; result.NewVersion = updateInfo.FutureReleaseEntry?.Version?.ToString(); UpdateInstalling?.Invoke(this, new SquirrelEventArgs(result)); var releaseEntry = await mgr.UpdateApp(); if (releaseEntry != null) { Log.Info("Update installed successfully"); result.NewVersion = releaseEntry.Version?.ToString(); } else { Log.Warning("Update finished, but no release entry was returned, falling back to previous update info"); } IsUpdatedInstalled = true; UpdateInstalled?.Invoke(this, new SquirrelEventArgs(result)); } } } catch (Exception ex) { Log.Error(ex, "An error occurred while checking for or installing the latest updates"); } return(result); }
private async Task ExecuteUpdateCheckLoop() { var current = GetCurrentLocalExe(); var latest = default(R1Executable); while (true) { Status = $"Checking for version newer than [{current.FileVersion}] ..."; latest = await _updatr.GetLatestVersions(); if (current.FileHash == latest.FileHash) { Status = $"Nothing new. Will check again in {_intervalMins} minutes ..."; await Task.Delay(1000 *_intervalMins * 60); } else { Status = $"Newer version found: [{latest.FileVersion}]. Downloading ..."; if (await DownloadAndSwap(latest)) { UpdateInstalled?.Raise(this); Status = "Updates downloaded and installed. Ready to relaunch."; return; } } } }
/// <summary> /// Handles the updates by installing them if there is an update available. /// </summary> /// <param name="maximumReleaseDate">The maximum release date.</param> /// <returns>Task.</returns> public async Task HandleUpdatesAsync(DateTime?maximumReleaseDate = null) { if (!_initialized) { throw Log.ErrorAndCreateException <InvalidOperationException>("Service is not initialized, call Initialize first"); } var checkForUpdates = _configurationService.GetValue <bool>(Settings.Application.AutomaticUpdates.CheckForUpdates); if (!checkForUpdates) { Log.Info("Automatic updates are disabled"); return; } var channelName = _configurationService.GetValue <string>(Settings.Application.AutomaticUpdates.UpdateChannel, string.Empty); var channelUrlSettingsName = Settings.Application.AutomaticUpdates.GetChannelSettingName(channelName); var channelUrl = _configurationService.GetValue <string>(channelUrlSettingsName, string.Empty); if (string.IsNullOrEmpty(channelUrl)) { Log.Warning("Cannot find url for channel '{0}'", channelName); return; } var entryAssemblyDirectory = AssemblyHelper.GetEntryAssembly().GetDirectory(); var updateExe = GetUpdateExecutable(); if (!File.Exists(updateExe)) { Log.Warning("Cannot check for updates, update.exe is not available"); return; } Log.Info("Calling update.exe for url '{0}'", channelUrl); await TaskHelper.Run(() => { try { if (!maximumReleaseDate.HasValue) { maximumReleaseDate = DateTime.MaxValue; } var startInfo = new ProcessStartInfo(updateExe); startInfo.Arguments = string.Format("--update={0} --md={1} --silent", channelUrl, maximumReleaseDate.Value.ToString("yyyyMMddHHmmss")); startInfo.WorkingDirectory = Path.GetFullPath("..", entryAssemblyDirectory); startInfo.UseShellExecute = true; startInfo.CreateNoWindow = true; var process = Process.Start(startInfo); process.WaitForExit(); Log.Debug("Update.exe exited with exit code '{0}'", process.ExitCode); // Possible exit codes: // -1 => An error occurred. Check the log file for more information about this error // 0 => No errors, no additional information available // 1 => New version available or new version is installed successfully (depending on switch /checkonly) // 2 => New version which is mandatory (forced) is available (for the future?) // 3 => No new version available switch (process.ExitCode) { case 1: IsUpdatedInstalled = true; UpdateInstalled.SafeInvoke(this); Log.Info("Installed new update"); break; case 4: IsUpdateOutsideMaintenanceAvailable = true; UpdateOutsideMaintenanceAvailable.SafeInvoke(this); Log.Info("New update is available but is outside maintenance, maintenance ended on '{0}'", maximumReleaseDate); break; } } catch (Exception ex) { Log.Error(ex, "Failed to check for updates"); } }, true); }
/// <summary> /// Installes the available updates if there is an update available. /// </summary> /// <returns>Task.</returns> public async Task <SquirrelResult> InstallAvailableUpdatesAsync(SquirrelContext context) { Argument.IsNotNull(() => context); var result = new SquirrelResult { IsUpdateInstalledOrAvailable = false, CurrentVersion = GetCurrentApplicationVersion() }; var channelUrl = GetChannelUrl(context); if (string.IsNullOrWhiteSpace(channelUrl)) { return(result); } try { // Do we actually have an update? Do a quick one here var checkResult = await CheckForUpdatesAsync(context); // Note that we don't want the process to stop updating, we only want to invoke if (checkResult.IsUpdateInstalledOrAvailable) { Log.Info($"Found new version '{checkResult.NewVersion}' using url '{channelUrl}', installing update..."); result.NewVersion = checkResult.NewVersion; UpdateInstalling?.Invoke(this, new SquirrelEventArgs(result)); } else { Log.Info($"Could not determine whether a new version was available for certain, going to run update anyway..."); } // Executable wrapper var startInfo = CreateUpdateProcessStartInfo($"--update={channelUrl}"); var process = Process.Start(startInfo); var line = "0"; while (!string.IsNullOrWhiteSpace(line)) { if (int.TryParse(line, out var progress)) { RaiseProgressChanged(progress); } line = await process.StandardOutput.ReadLineAsync(); } process.WaitForExit(); // Only when we knew there was an update pending, we notify if (process.ExitCode == 0 && checkResult.IsUpdateInstalledOrAvailable) { result.NewVersion = checkResult?.NewVersion ?? "unknown"; result.IsUpdateInstalledOrAvailable = true; Log.Info("Update installed successfully"); IsUpdatedInstalled = true; UpdateInstalled?.Invoke(this, new SquirrelEventArgs(result)); Log.Info("Update installed successfully"); } } catch (Exception ex) { Log.Error(ex, "An error occurred while checking for or installing the latest updates"); } return(result); }