private static bool CompareChecksum(string fileName, string checksum)
        {
            using (var hashAlgorithm = HashAlgorithm.Create(AutoUpdater.HashingAlgorithm))
            {
                using (var stream = File.OpenRead(fileName))
                {
                    if (hashAlgorithm != null)
                    {
                        var hash         = hashAlgorithm.ComputeHash(stream);
                        var fileChecksum = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant();

                        if (fileChecksum == checksum.ToLower())
                        {
                            return(true);
                        }

                        AutoUpdater.LogLine($"File integrity check failed.");
                    }
                    else
                    {
                        AutoUpdater.LogLine($"Hash algorithm not supported.");
                    }

                    return(false);
                }
            }
        }
        private void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage >= _nextReport)
            {
                _nextReport += 10;

                AutoUpdater.LogLine($"Downloaded {e.BytesReceived}/{e.TotalBytesToReceive} bytes ({e.ProgressPercentage}%).");
            }
        }
        private void WebClientOnDownloadFileCompleted(object sender, AsyncCompletedEventArgs asyncCompletedEventArgs)
        {
            if (asyncCompletedEventArgs.Cancelled)
            {
                AutoUpdater.LogLine($"Download cancelled.");
                return;
            }

            if (asyncCompletedEventArgs.Error != null)
            {
                AutoUpdater.LogLine($"Download failed with error: {asyncCompletedEventArgs.Error.Message}");
                _webClient = null;
                return;
            }

            if (!string.IsNullOrEmpty(AutoUpdater.Checksum))
            {
                if (!CompareChecksum(_tempFile, AutoUpdater.Checksum))
                {
                    AutoUpdater.LogLine($"Checksum comparison failed.");
                    _webClient = null;
                    return;
                }
            }

            string fileName;
            string contentDisposition = _webClient.ResponseHeaders["Content-Disposition"] ?? string.Empty;

            if (string.IsNullOrEmpty(contentDisposition))
            {
                fileName = Path.GetFileName(_webClient.ResponseUri.LocalPath);
            }
            else
            {
                fileName = TryToFindFileName(contentDisposition, "filename=");
                if (string.IsNullOrEmpty(fileName))
                {
                    fileName = TryToFindFileName(contentDisposition, "filename*=UTF-8''");
                }
            }

            var tempPath = Path.Combine(string.IsNullOrEmpty(AutoUpdater.DownloadPath) ? Path.GetTempPath() : AutoUpdater.DownloadPath, fileName);

            try
            {
                if (File.Exists(tempPath))
                {
                    File.Delete(tempPath);
                }

                File.Move(_tempFile, tempPath);
            }
            catch (Exception e)
            {
                AutoUpdater.LogLine($"File operation failed with error: {e.Message}");
                _webClient = null;
                return;
            }

            var processStartInfo = new ProcessStartInfo
            {
                FileName        = tempPath,
                UseShellExecute = true,
                Arguments       = AutoUpdater.InstallerArgs.Replace("%path%", Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName))
            };

            var extension = Path.GetExtension(tempPath);

            if (extension.Equals(".zip", StringComparison.OrdinalIgnoreCase))
            {
                string installerPath = Path.Combine(Path.GetDirectoryName(tempPath), "ZipExtractor.exe");
                File.WriteAllBytes(installerPath, Resources.ZipExtractor);
                StringBuilder arguments = new StringBuilder($"\"{tempPath}\" \"{Process.GetCurrentProcess().MainModule.FileName}\"");
                string[]      args      = Environment.GetCommandLineArgs();
                for (int i = 1; i < args.Length; i++)
                {
                    if (i.Equals(1))
                    {
                        arguments.Append(" \"");
                    }
                    arguments.Append(args[i]);
                    arguments.Append(i.Equals(args.Length - 1) ? "\"" : " ");
                }
                processStartInfo = new ProcessStartInfo
                {
                    FileName        = installerPath,
                    UseShellExecute = true,
                    Arguments       = arguments.ToString()
                };
            }
            else if (extension.Equals(".msi", StringComparison.OrdinalIgnoreCase))
            {
                processStartInfo = new ProcessStartInfo
                {
                    FileName  = "msiexec",
                    Arguments = $"/i \"{tempPath}\""
                };
            }

            if (AutoUpdater.RunUpdateAsAdmin)
            {
                processStartInfo.Verb = "runas";
            }

            try
            {
                AutoUpdater.LogLine($"Starting installer...");

                Process.Start(processStartInfo);
            }
            catch (Win32Exception exception)
            {
                AutoUpdater.LogLine($"Installer could not be started: {exception.Message}");

                _webClient = null;
                if (exception.NativeErrorCode != 1223)
                {
                    throw;
                }
            }
        }