Ejemplo n.º 1
0
        private void SleepIfNecessary()
        {
            SleepControls.AllowSleepOrShutdown(Handle);

            if (checkBoxSleep.Checked)
            {
                if (!SleepControls.PutToSleep())
                {
                    MessageBox.Show("Sleep when done", "Could not put the PC to sleep for some reason :(",
                                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }

            checkBoxSleep.Enabled = false;
        }
Ejemplo n.º 2
0
        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 async void ModUpdateProgress_Shown(object sender, EventArgs e)
        {
            try
            {
                progressBar1.Style   = ProgressBarStyle.Marquee;
                progressBar1.Value   = 0;
                progressBar1.Maximum = 1;

                labelPercent.Text = "";

                checkBoxSleep.Enabled = false;

                var random = new Random();
                if (random.Next(0, 10) >= 9)
                {
                    var offset    = random.Next(0, 136);
                    var offsetStr = new string(Enumerable.Repeat(' ', offset).ToArray());
                    labelPercent.Text  = offsetStr + " ( )  ( )\n";
                    labelPercent.Text += offsetStr + "( o . o)";
                }

                SetStatus("Preparing...");
                if (await ProcessWaiter.CheckForProcessesBlockingKoiDir() == false)
                {
                    throw new OperationCanceledException();
                }

                SetStatus("Searching for mod updates...");
                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();
                }

                SleepControls.PreventSleepOrShutdown(Handle, "Update is in progress");

                _overallSize   = FileSize.SumFileSizes(updateTasks.Select(x => x.TotalUpdateSize));
                _completedSize = FileSize.Empty;

                var allItems = updateTasks.SelectMany(x => x.GetUpdateItems())
                               // Remove unnecessary to avoid potential conflicts if the update is aborted midway and a newer version is added
                               .OrderByDescending(sources => sources.Any(x => x.Item2 is DeleteFileUpdateItem))
                               // Try items with a single source first since they are the most risky
                               .ThenBy(sources => sources.Count())
                               .ThenBy(sources => sources.FirstOrDefault()?.Item2.TargetPath.FullName)
                               .ToList();

                SetStatus($"{allItems.Count(items => items.Count() > 1)} out of {allItems.Count} items have more than 1 source", false, true);

                progressBar1.Maximum = 1000;

                checkBoxSleep.Enabled = true;

                for (var index = 0; index < allItems.Count; index++)
                {
                    _cancelToken.Token.ThrowIfCancellationRequested();

                    var task = allItems[index];

                    SetStatus("Downloading " + task.First().Item2.TargetPath.Name);

                    await UpdateSingleItem(task);
                }

                var s = $"Successfully updated/removed {allItems.Count - _failedItems.Count} 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);
                if (_failedExceptions.Any())
                {
                    var failDetails = "Reason(s) for failing:\n" + string.Join("\n", _failedExceptions.Select(x => x.Message).Distinct());
                    Console.WriteLine(failDetails);
                    s += " " + failDetails;
                }

                SleepIfNecessary();

                MessageBox.Show(s, "Finished updating", MessageBoxButtons.OK, MessageBoxIcon.Information);
                PerformAutoScale();
            }
            catch (OutdatedVersionException ex)
            {
                SetStatus("KK Manager needs to be updated to get updates.", true, true);
                ex.ShowKkmanOutdatedMessage();
            }
            catch (OperationCanceledException)
            {
                SetStatus("Operation 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("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
            {
                checkBoxSleep.Enabled = false;

                var wasCancelled = _cancelToken.IsCancellationRequested;
                _cancelToken.Cancel();

                labelPercent.Text = wasCancelled ? "Update was cancelled" : "Update finished";

                if (_completedSize != FileSize.Empty)
                {
                    labelPercent.Text += $"\nSuccessfully downloaded {_completedSize} out of {_overallSize}.";
                }

                progressBar1.Style = ProgressBarStyle.Blocks;
                button1.Enabled    = true;
                button1.Text       = "OK";

                if (_autoInstallGuids != null && _autoInstallGuids.Length > 0)
                {
                    Close();
                }

                SleepControls.AllowSleepOrShutdown(Handle);
            }
        }
        private UninstallProgressWindow()
        {
            InitializeComponent();

            Text += " - Bulk Crap Uninstaller";

            Opacity = 0;

            Icon = Resources.Icon_Logo;

            toolStrip1.Renderer = new ToolStripProfessionalRenderer(new StandardSystemColorTable());

            // Shutdown blocking not available below Windows Vista
            if (Environment.OSVersion.Version >= new Version(6, 0))
            {
                _settings.Subscribe((sender, args) =>
                {
                    if (args.NewValue)
                    {
                        SleepControls.PreventSleepOrShutdown(Handle, "Bulk uninstallation is in progress.");
                    }
                    else
                    {
                        SleepControls.AllowSleepOrShutdown(Handle);
                    }
                }, settings => settings.UninstallPreventShutdown, this);
            }

            _settings.SendUpdates(this);

            FormClosing += (sender, args) =>
            {
                if (args.CloseReason == CloseReason.WindowsShutDown && _settings.Settings.UninstallPreventShutdown)
                {
                    args.Cancel = true;
                }
            };

            FormClosed += (o, eventArgs) =>
            {
                _settings.RemoveHandlers(this);

                SleepControls.AllowSleepOrShutdown(Handle);

                _walkAwayBox?.Dispose();
            };

            olvColumnName.AspectGetter     = BulkUninstallTask.DisplayNameAspectGetter;
            olvColumnStatus.AspectGetter   = BulkUninstallTask.StatusAspectGetter;
            olvColumnIsSilent.AspectGetter = BulkUninstallTask.IsSilentAspectGetter;
            olvColumnId.AspectName         = nameof(BulkUninstallEntry.Id);

            olvColumnStatus.GroupKeyGetter = rowObject => (rowObject as BulkUninstallEntry)?.CurrentStatus;
            olvColumnName.GroupKeyGetter   = rowObject => (rowObject as BulkUninstallEntry)?.UninstallerEntry.DisplayName.SafeNormalize().FirstOrDefault();
            olvColumnId.GroupKeyGetter     = rowObject => (rowObject as BulkUninstallEntry)?.Id / 10;

            objectListView1.PrimarySortColumn   = olvColumnStatus;
            objectListView1.SecondarySortColumn = olvColumnId;

            forceUpdateTimer.Tick += (o, args) =>
            {
                if (_currentTargetStatus != null && !_currentTargetStatus.Finished)
                {
                    currentTargetStatus_OnCurrentTaskChanged(o, args);
                }
                else
                {
                    forceUpdateTimer.Stop();
                }
            };

            // Handle sleeping after task finishes
            sleepTimer.Interval = 1000;
            sleepTimer.Tick    += (sender, args) =>
            {
                if (_currentTargetStatus.Finished && checkBoxFinishSleep.Checked)
                {
                    _sleepTimePassed++;

                    const int sleepDelay = 30;
                    label1.Text = Localisable.UninstallProgressWindow_TaskDone + "\n" +
                                  string.Format(Localisable.UninstallProgressWindow_StatusPuttingToSleepInSeconds, sleepDelay - _sleepTimePassed);

                    if (_sleepTimePassed > sleepDelay)
                    {
                        checkBoxFinishSleep.Checked = false;
                        checkBoxFinishSleep.Enabled = false;

                        SleepControls.AllowSleepOrShutdown(Handle);
                        SleepControls.PutToSleep();
                    }
                }
                else
                {
                    _sleepTimePassed = 0;
                    if (_currentTargetStatus.Finished)
                    {
                        label1.Text = Localisable.UninstallProgressWindow_TaskDone;
                    }
                }
            };
        }