Exemplo n.º 1
0
        public async Task <Result> CheckForUpdatesAsync()
        {
            try
            {
                this.Show();

#if DEBUG
                const bool SkipUpdate = true;
#else
                const bool SkipUpdate = false;
#endif

                var curProcess         = Process.GetCurrentProcess();
                var processFilePath    = curProcess.MainModule?.FileName;
                var processFileOldPath = $"{processFilePath}.old";

                if (string.IsNullOrEmpty(processFilePath))
                {
                    MessageBox.Show(this,
                                    "Fatal error...could not locate the running program on the file system.",
                                    "Update Failed",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);

                    return(Result.Failed);
                }

                var otherProcesses = Process.GetProcessesByName(curProcess.ProcessName)
                                     .Where(p => p.Id != curProcess.Id);

                foreach (var process in otherProcesses)
                {
                    process.WaitForExit(3000);
                    process.Kill();
                }

                if (File.Exists(processFileOldPath))
                {
                    File.Delete(processFileOldPath);
                }

                using var web = new WebClient();

                var localHash  = CryptoUtility.CalculateFileMd5(processFilePath);
                var remoteHash = await web.DownloadStringTaskAsync(this.remoteMd5Url);

                // ReSharper disable once RedundantLogicalConditionalExpressionOperand
                // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                if (SkipUpdate || localHash == remoteHash)
                {
                    return(Result.NoUpdateNeeded);
                }

                this.lbStatus.Text    = "Updating program...";
                this.pbDownload.Style = ProgressBarStyle.Continuous;

                web.DownloadProgressChanged += (o, e) => this.Invoke(new Action(() => {
                    var dlSize    = e.BytesReceived.Bytes();
                    var totalSize = e.TotalBytesToReceive.Bytes();

                    this.lbProgress.Text  = $"Downloading updates... {dlSize.ToString("0.##")} / {totalSize.ToString("0.##")} ({e.ProgressPercentage}%)";
                    this.pbDownload.Value = e.ProgressPercentage;
                }));

                var updateFilePath = Path.Combine(Path.GetTempPath(), "MinecraftLauncher.exe");

                if (File.Exists(updateFilePath))
                {
                    File.Delete(updateFilePath);
                }

                await web.DownloadFileWrappedAsync(this.remoteFileUrl, updateFilePath);

                this.lbStatus.Text    = "Installing updates...";
                this.pbDownload.Style = ProgressBarStyle.Marquee;

                File.Move(processFilePath, processFileOldPath);
                File.Move(updateFilePath, processFilePath);

                var newLocalHash = CryptoUtility.CalculateFileMd5(processFilePath);

                if (newLocalHash != remoteHash)
                {
                    MessageBox.Show(this,
                                    "Checksum mismatch! The update file is invalid. Update failed.",
                                    "Update Failed",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);

                    File.Delete(processFilePath);
                    File.Move(processFileOldPath, processFilePath);

                    return(Result.Failed);
                }

                MessageBox.Show(this,
                                "Update complete! Click OK to restart the program and apply the update.",
                                "Update Complete",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);

                Process.Start(new ProcessStartInfo {
                    FileName        = processFilePath,
                    UseShellExecute = true,
                });

                return(Result.NeedsRestart);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in updater:");
                Console.WriteLine(ex);
                throw;
            }
            finally
            {
                this.Close();
            }
        }