private static ApplicationUninstallerEntry GetSteamUninstallerEntry() { if (string.IsNullOrEmpty(SteamFactory.SteamLocation)) { return(null); } return(new ApplicationUninstallerEntry { AboutUrl = @"http://store.steampowered.com/about/", InstallLocation = SteamFactory.SteamLocation, DisplayIcon = Path.Combine(SteamFactory.SteamLocation, "Steam.exe"), DisplayName = "Steam", UninstallerKind = UninstallerType.Nsis, UninstallString = Path.Combine(SteamFactory.SteamLocation, "uninstall.exe"), IsOrphaned = true, IsValid = File.Exists(Path.Combine(SteamFactory.SteamLocation, "uninstall.exe")), InstallDate = Directory.GetCreationTime(SteamFactory.SteamLocation), Publisher = "Valve Corporation", // Prevent very long size scan in case of many games, the install itself is about 600-800MB EstimatedSize = FileSize.FromKilobytes(1024 * 700) }); }
private async void ModUpdateProgress_Shown(object sender, EventArgs e) { var averageDownloadSpeed = new MovingAverage(20); var downloadStartTime = DateTime.MinValue; try { #region Initialize UI progressBar1.Style = ProgressBarStyle.Marquee; progressBar1.Value = 0; progressBar1.Maximum = 1; labelPercent.Text = ""; checkBoxSleep.Enabled = false; var random = new Random(); if (random.Next(0, 10) >= 8) { var offset = random.Next(20, 80); var offsetStr = new string(Enumerable.Repeat(' ', offset).ToArray()); labelPercent.Text = offsetStr + " ( ) ( )\n"; labelPercent.Text += offsetStr + "( o . o)"; } olvColumnProgress.Renderer = new BarRenderer(0, 100); olvColumnProgress.AspectGetter = rowObject => (int)Math.Round(((UpdateDownloadItem)rowObject).FinishPercent); olvColumnSize.AspectGetter = rowObject => ((UpdateDownloadItem)rowObject).TotalSize; //olvColumnDownloaded.AspectGetter = rowObject => ((UpdateDownloadItem)rowObject).GetDownloadedSize(); olvColumnStatus.AspectGetter = rowObject => { var item = (UpdateDownloadItem)rowObject; return(item.Exceptions.Count == 0 ? item.Status.ToString() : item.Status + " - " + string.Join("; ", item.Exceptions.Select(x => x.Message))); }; olvColumnName.AspectGetter = rowObject => ((UpdateDownloadItem)rowObject).DownloadPath.Name; olvColumnNo.AspectGetter = rowObject => ((UpdateDownloadItem)rowObject).Order; fastObjectListView1.PrimarySortColumn = olvColumnStatus; fastObjectListView1.SecondarySortColumn = olvColumnNo; fastObjectListView1.Sorting = SortOrder.Ascending; fastObjectListView1.PrimarySortOrder = SortOrder.Ascending; fastObjectListView1.SecondarySortOrder = SortOrder.Ascending; fastObjectListView1.ShowSortIndicators = true; fastObjectListView1.Sort(); fastObjectListView1.ShowSortIndicator(); _overallSize = _completedSize = FileSize.Empty; #endregion SetStatus("Preparing..."); if (await ProcessWaiter.CheckForProcessesBlockingKoiDir() == false) { throw new OperationCanceledException(); } #region Find and select updates SetStatus("Searching for mod updates..."); labelPercent.Text = "Please wait, this might take a couple of minutes."; var updateTasks = await UpdateSourceManager.GetUpdates(_cancelToken.Token, _updaters, _autoInstallGuids); _cancelToken.Token.ThrowIfCancellationRequested(); progressBar1.Style = ProgressBarStyle.Blocks; if (updateTasks.All(x => x.UpToDate)) { SetStatus("Everything is up to date!"); progressBar1.Value = progressBar1.Maximum; _cancelToken.Cancel(); return; } var isAutoInstall = _autoInstallGuids != null && _autoInstallGuids.Length > 0; if (!isAutoInstall) { SetStatus($"Found {updateTasks.Count} updates, waiting for user confirmation."); updateTasks = ModUpdateSelectDialog.ShowWindow(this, updateTasks); } else { var skipped = updateTasks.RemoveAll(x => x.UpToDate); SetStatus($"Found {updateTasks.Count} update tasks in silent mode, {skipped} are already up-to-date.", true, true); } if (updateTasks == null) { throw new OperationCanceledException(); } #endregion SleepControls.PreventSleepOrShutdown(Handle, "Update is in progress"); #region Set up update downloader and start downloading downloadStartTime = DateTime.Now; var downloader = UpdateDownloadCoordinator.Create(updateTasks); var downloadItems = downloader.UpdateItems; SetStatus($"{downloadItems.Count(items => items.DownloadSources.Count > 1)} out of {downloadItems.Count} items have more than 1 source", false, true); fastObjectListView1.Objects = downloadItems; progressBar1.Maximum = 1000; progressBar1.Value = 0; checkBoxSleep.Enabled = true; _overallSize = FileSize.SumFileSizes(downloadItems.Select(x => x.TotalSize)); var lastCompletedSize = FileSize.Empty; updateTimer.Tick += (o, args) => { var itemCount = fastObjectListView1.GetItemCount(); if (itemCount > 0) { fastObjectListView1.BeginUpdate(); fastObjectListView1.RedrawItems(0, itemCount - 1, true); // Needed if user changes sorting column //fastObjectListView1.SecondarySortColumn = olvColumnNo; fastObjectListView1.Sort(); fastObjectListView1.EndUpdate(); } _completedSize = FileSize.SumFileSizes(downloadItems.Select(x => x.GetDownloadedSize())); var totalPercent = (double)_completedSize.GetKbSize() / (double)_overallSize.GetKbSize() * 100d; if (double.IsNaN(totalPercent)) { totalPercent = 0; } // Download speed calc var secondsPassed = updateTimer.Interval / 1000d; var downloadedSinceLast = FileSize.FromKilobytes((long)((_completedSize - lastCompletedSize).GetKbSize() / secondsPassed)); lastCompletedSize = _completedSize; averageDownloadSpeed.Sample(downloadedSinceLast.GetKbSize()); var etaSeconds = (_overallSize - _completedSize).GetKbSize() / (double)averageDownloadSpeed.GetAverage(); var eta = double.IsNaN(etaSeconds) || etaSeconds <0 || etaSeconds> TimeSpan.MaxValue.TotalSeconds ? "Unknown" : TimeSpan.FromSeconds(etaSeconds).GetReadableTimespan(); labelPercent.Text = $"Overall: {totalPercent:F1}% done ({_completedSize} out of {_overallSize})\r\n" + $"Speed: {downloadedSinceLast}/s (ETA: {eta})"; //$"Speed: {downloadedSinceLast:F1}KB/s"; progressBar1.Value = Math.Min((int)Math.Round(totalPercent * 10), progressBar1.Maximum); }; updateTimer.Start(); SetStatus("Downloading updates...", true, true); await downloader.RunUpdate(_cancelToken.Token); _cancelToken.Token.ThrowIfCancellationRequested(); #endregion #region Show finish messages var failedItems = downloadItems.Where(x => x.Status == UpdateDownloadStatus.Failed).ToList(); var unfinishedCount = downloadItems.Count(x => x.Status != UpdateDownloadStatus.Finished); var s = $"Successfully updated/removed {downloadItems.Count - unfinishedCount} files from {updateTasks.Count} tasks."; if (failedItems.Any()) { s += $"\nFailed to update {failedItems.Count} files because some sources crashed. Check log for details."; } SetStatus(s, true, true); updateTimer.Stop(); progressBar1.Value = progressBar1.Maximum; labelPercent.Text = ""; if (failedItems.Any(x => x.Exceptions.Count > 0)) { var exceptionMessages = failedItems .SelectMany(x => x.Exceptions) .Where(y => !(y is DownloadSourceCrashedException)) // Deal with wrapped exceptions .Select(y => y.Message.Contains("InnerException") && y.InnerException != null ? y.InnerException.Message : y.Message) .Distinct(); var failDetails = "Reason(s) for failing:\n" + string.Join("\n", exceptionMessages); Console.WriteLine(failDetails); s += " " + failDetails; } // Sleep before showing a messagebox since the box will block until user clicks ok SleepIfNecessary(); MessageBox.Show(s, "Finished updating", MessageBoxButtons.OK, MessageBoxIcon.Information); #endregion } catch (OutdatedVersionException ex) { SetStatus("KK Manager needs to be updated to get updates.", true, true); ex.ShowKkmanOutdatedMessage(); } catch (OperationCanceledException) { SetStatus("Update was cancelled by the user.", true, true); } catch (Exception ex) { var exceptions = ex is AggregateException aex?aex.Flatten().InnerExceptions : (ICollection <Exception>) new[] { ex }; if (!exceptions.Any(x => x is OperationCanceledException)) { SleepIfNecessary(); } SetStatus("Unexpected crash while updating mods, aborting.", true, true); SetStatus(string.Join("\n---\n", exceptions), false, true); MessageBox.Show("Something unexpected happened and the update could not be completed. Make sure that your internet connection is stable, " + "and that you did not hit your download limits, then try again.\n\nError message (check log for more):\n" + string.Join("\n", exceptions.Select(x => x.Message)), "Update failed", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { updateTimer.Stop(); checkBoxSleep.Enabled = false; fastObjectListView1.EmptyListMsg = "Nothing was downloaded"; _cancelToken.Cancel(); labelPercent.Text = ""; if (_completedSize != FileSize.Empty) { labelPercent.Text += $"Downloaded {_completedSize} out of {_overallSize}"; if (downloadStartTime != DateTime.MinValue) { var timeSpent = DateTime.Now - downloadStartTime; labelPercent.Text += $" in {timeSpent.GetReadableTimespan()}"; } labelPercent.Text += "\n"; } var averageDlSpeed = averageDownloadSpeed.GetAverage(); if (averageDlSpeed > 0) { labelPercent.Text += $"Average download speed: {new FileSize(averageDlSpeed)}/s"; } progressBar1.Style = ProgressBarStyle.Blocks; button1.Enabled = true; button1.Text = "OK"; if (_autoInstallGuids != null && _autoInstallGuids.Length > 0) { Close(); } SleepControls.AllowSleepOrShutdown(Handle); } }
private static ApplicationUninstallerEntry GetOneDrive() { var result = new ApplicationUninstallerEntry(); // Check if installed try { using (var key = RegistryTools.OpenRegistryKey(@"HKEY_CURRENT_USER\SOFTWARE\Microsoft\OneDrive", false)) { result.RegistryPath = key.Name; result.RegistryKeyName = key.GetKeyName(); result.InstallLocation = key.GetValue("CurrentVersionPath") as string; if (result.InstallLocation == null || !Directory.Exists(result.InstallLocation)) { return(null); } result.DisplayIcon = key.GetValue("OneDriveTrigger") as string; result.DisplayVersion = ApplicationEntryTools.CleanupDisplayVersion(key.GetValue("Version") as string); } } catch { return(null); } // Check if the uninstaller is available var systemRoot = WindowsTools.GetEnvironmentPath(CSIDL.CSIDL_WINDOWS); var uninstallPath = Path.Combine(systemRoot, @"System32\OneDriveSetup.exe"); if (!File.Exists(uninstallPath)) { uninstallPath = Path.Combine(systemRoot, @"SysWOW64\OneDriveSetup.exe"); if (!File.Exists(uninstallPath)) { uninstallPath = null; } } if (uninstallPath != null) { result.IsValid = true; result.UninstallString = $"\"{uninstallPath}\" /uninstall"; result.QuietUninstallString = result.UninstallString; if (!File.Exists(result.DisplayIcon)) { result.DisplayIcon = uninstallPath; } } result.AboutUrl = @"https://onedrive.live.com/"; result.RawDisplayName = "OneDrive"; result.Publisher = "Microsoft Corporation"; result.EstimatedSize = FileSize.FromKilobytes(1024 * 90); result.Is64Bit = MachineType.X86; result.IsRegistered = true; result.UninstallerKind = UninstallerType.Unknown; result.InstallDate = Directory.GetCreationTime(result.InstallLocation); if (!string.IsNullOrEmpty(result.DisplayIcon)) { result.IconBitmap = UninstallToolsGlobalConfig.TryExtractAssociatedIcon(result.DisplayIcon); } return(result); }
private static FileSize GetEstimatedSize(RegistryKey uninstallerKey) { var tempSize = (int)uninstallerKey.GetValue(ApplicationUninstallerEntry.RegistryNameEstimatedSize, 0); return(FileSize.FromKilobytes(tempSize)); }
private async Task <bool> UpdateSingleItem(IGrouping <string, Tuple <UpdateInfo, UpdateItem> > task) { var firstItem = task.First().Item2; var itemSize = firstItem.GetDownloadSize(); var lastTimestamp = DateTime.UtcNow; var lastDownloadedKBytes = 0l; var progress = new Progress <double>(thisPercent => { var timeNow = DateTime.UtcNow; var secondsSinceLastUpdate = (timeNow - lastTimestamp).TotalSeconds; if (secondsSinceLastUpdate < 1 && thisPercent < 100) { return; } //This item: 70% done (1MB / 20MB) //Overall: 50% done (111MB / 1221MB) //Speed: 1234KB/s (average 1111KB/s) var downloadedKBytes = (long)(itemSize.GetRawSize() * (thisPercent / 100d)); var downloadedSize = FileSize.FromKilobytes(downloadedKBytes); var totalDownloadedSize = _completedSize + downloadedSize; var totalPercent = ((double)totalDownloadedSize.GetRawSize() / (double)_overallSize.GetRawSize()) * 100d; var speed = (downloadedKBytes - lastDownloadedKBytes) / secondsSinceLastUpdate; if (double.IsNaN(speed)) { speed = 0; } lastDownloadedKBytes = downloadedKBytes; lastTimestamp = timeNow; labelPercent.Text = $@"This item: {thisPercent:F1}% done ({downloadedSize} / {itemSize}) Overall: {totalPercent:F1}% done ({totalDownloadedSize} / {_overallSize}) Speed: {speed:F1}KB/s"; progressBar1.Value = Math.Min((int)(totalPercent * 10), progressBar1.Maximum); }); SetStatus($"Updating {firstItem.TargetPath.Name}"); SetStatus($"Updating {InstallDirectoryHelper.GetRelativePath(firstItem.TargetPath)}", false, true); var sourcesToAttempt = task.Where(x => !_badUpdateSources.Contains(x.Item1)).OrderBy(x => GetPing(x.Item1)).ToList(); if (sourcesToAttempt.Count == 0) { Console.WriteLine("There are no working sources to download from. Check the log for reasons why the sources failed."); _failedItems.Add(task); return(false); } Exception ex = null; foreach (var source in sourcesToAttempt) { try { // Needed because ZipUpdater doesn't support progress if (source.Item2.RemoteFile is ZipUpdater.ArchiveItem) { labelPercent.Text = $"Extracting... Overall progress: {_completedSize} / {_overallSize}."; } await RetryHelper.RetryOnExceptionAsync(() => source.Item2.Update(progress, _cancelToken.Token), 3, TimeSpan.FromSeconds(3), _cancelToken.Token); _completedSize += source.Item2.GetDownloadSize(); ex = null; break; } catch (OperationCanceledException) { throw; } catch (Exception e) { Console.WriteLine($"Marking source {source.Item1.Source.Origin} as broken because of exception: {e.ToStringDemystified()}"); ex = e; _badUpdateSources.Add(source.Item1); } } // Check if all sources failed if (ex != null) { Console.WriteLine("There are no working sources to download from. Check the log for reasons why the sources failed."); _failedItems.Add(task); _failedExceptions.Add(ex); return(false); } return(true); }