/// <summary> /// Downloads the latest version of this package. If a version is already in the local store, it will be deleted first. /// </summary> /// <param name="displayErrorMessage">Indicates whether to display error message boxes when an error occurs.</param> /// <returns>A task that completes when the latest version has been downloaded.</returns> /// <remarks> /// This method will invoke, from a worker thread, <see cref="BeforeDownload"/> before doing anything, and <see cref="AfterDownload"/> /// if the download successfully completed without exception. In every case, it will also invoke <see cref="UpdateVersionsFromStore"/> /// before completing. /// </remarks> protected Task Download(bool displayErrorMessage) { BeforeDownload(); return(Task.Run(async() => { IsProcessing = true; // Uninstall previous version first, if it exists if (LocalPackage != null) { try { CurrentProcessStatus = null; using (var progressReport = new ProgressReport(Store, ServerPackage)) { progressReport.ProgressChanged += (action, progress) => { Dispatcher.InvokeAsync(() => { UpdateProgress(action, progress); }).Forget(); }; progressReport.UpdateProgress(ProgressAction.Delete, -1); await Store.UninstallPackage(LocalPackage, progressReport); CurrentProcessStatus = null; } } catch (Exception e) { if (displayErrorMessage) { var message = $"{UninstallErrorMessage}{e.FormatSummary(true)}"; await ServiceProvider.Get <IDialogService>().MessageBox(message, MessageBoxButton.OK, MessageBoxImage.Error); await UpdateVersionsFromStore(); IsProcessing = false; return; } IsProcessing = false; throw; } } // Then download and install the latest version. bool downloadCompleted = false; try { using (var progressReport = new ProgressReport(Store, ServerPackage)) { progressReport.ProgressChanged += (action, progress) => { Dispatcher.InvokeAsync(() => { UpdateProgress(action, progress); }).Forget(); }; progressReport.UpdateProgress(ProgressAction.Install, -1); MetricsHelper.NotifyDownloadStarting(ServerPackage.Id, ServerPackage.Version.ToString()); await Store.InstallPackage(ServerPackage.Id, ServerPackage.Version, progressReport); downloadCompleted = true; MetricsHelper.NotifyDownloadCompleted(ServerPackage.Id, ServerPackage.Version.ToString()); } AfterDownload(); } catch (Exception e) { if (!downloadCompleted) { MetricsHelper.NotifyDownloadFailed(ServerPackage.Id, ServerPackage.Version.ToString()); } // Rollback: try to delete the broken package (i.e. if it is installed with NuGet but had a failure during Install scripts) try { var localPackage = Store.FindLocalPackage(ServerPackage.Id, ServerPackage.Version); if (localPackage != null) { await Store.UninstallPackage(localPackage, null); } } catch { // Note: quite a bad state: rollback (uninstall) failed // we don't display the message to not confuse the user even more with an intermediate uninstall error message before the install error message } if (displayErrorMessage) { var message = $"{InstallErrorMessage}{e.FormatSummary(true)}"; await ServiceProvider.Get <IDialogService>().MessageBox(message, MessageBoxButton.OK, MessageBoxImage.Error); return; } throw; } finally { await UpdateVersionsFromStore(); IsProcessing = false; } })); }