示例#1
0
        private async void OnDownloadFinished(AppCastItem item, string path)
        {
            _progressText.Text = Loc.Resolve("updater_dl_progress_finished");

            try
            {
                new FileInfo(path).DeleteAlternateDataStream("Zone.Identifier");

                Process proc = new Process
                {
                    StartInfo =
                    {
                        FileName        = path,
                        UseShellExecute = true,
                        Verb            = "runas"
                    }
                };
                proc.Start();
            }
            catch (Exception exception)
            {
                Log.Warning("UpdateProgressPage: Exception raised while launching installer: " + exception.Message);
            }

            if (BluetoothImpl.Instance.IsConnected)
            {
                await BluetoothImpl.Instance.DisconnectAsync();
            }

            await Task.Delay(100);

            Environment.Exit(0);
        }
示例#2
0
        private async void LoadReleaseNotes(List <AppCastItem> items, bool isforallversions)
        {
            AppCastItem latestVersion = items.OrderByDescending(p => p.Version).FirstOrDefault();
            string      releaseNotes  = null;

            if (!isforallversions)
            {
                releaseNotes = await _releaseNotesGrabber.DownloadAllReleaseNotes(items, latestVersion, _cancellationToken);
            }
            else
            {
                releaseNotes = await _releaseNotesGrabber.DownloadAllReleaseNotesWithButtons(items, latestVersion, _cancellationToken);
            }
            ReleaseNotesBrowser.Invoke((MethodInvoker) delegate
            {
                // see https://stackoverflow.com/a/15209861/3938401
                ReleaseNotesBrowser.ObjectForScripting = this;


                ReleaseNotesBrowser.Navigate("about:blank");
                ReleaseNotesBrowser.Document.OpenNew(true);
                ReleaseNotesBrowser.Document.Write(releaseNotes);
                ReleaseNotesBrowser.DocumentText = releaseNotes;
            });
        }
        public async void InstallUpdate(AppCastItem item, string installPath = null)
        {
            var path = installPath != null && File.Exists(installPath)
                ? installPath
                : await GetDownloadPathForAppCastItem(item);

            if (File.Exists(path))
            {
                NetSparkleUpdater.Enums.ValidationResult result;
                try
                {
                    result = SignatureVerifier.VerifySignatureOfFile(item.DownloadSignature, path);
                }
                catch (Exception exc)
                {
                    Log.Error("Error validating signature of file: {0}; {1}", exc.Message,
                              exc.StackTrace);
                    result = NetSparkleUpdater.Enums.ValidationResult.Invalid;
                }

                if (result == NetSparkleUpdater.Enums.ValidationResult.Valid)
                {
                    await RunDownloadedInstaller(path);
                }
            }
        }
示例#4
0
        /// <summary>
        /// Parse the app cast XML string into a list of <see cref="AppCastItem"/> objects.
        /// When complete, the Items list should contain the parsed information
        /// as <see cref="AppCastItem"/> objects.
        /// </summary>
        /// <param name="appCast">the non-null string XML app cast</param>
        protected virtual void ParseAppCast(string appCast)
        {
            const string itemNode = "item";

            Items.Clear();

            XDocument doc     = XDocument.Parse(appCast);
            var       rss     = doc?.Element("rss");
            var       channel = rss?.Element("channel");

            Title    = channel?.Element("title")?.Value ?? string.Empty;
            Language = channel?.Element("language")?.Value ?? "en";

            var items = doc.Descendants(itemNode);

            foreach (var item in items)
            {
                var currentItem = AppCastItem.Parse(_config.InstalledVersion, _config.ApplicationName, _castUrl, item, _logWriter);
                _logWriter.PrintMessage("Found an item in the app cast: version {0} ({1}) -- os = {2}",
                                        currentItem?.Version, currentItem?.ShortVersion, currentItem.OperatingSystemString);
                Items.Add(currentItem);
            }

            // sort versions in reverse order
            Items.Sort((item1, item2) => - 1 * item1.CompareTo(item2));
        }
示例#5
0
        public async void CBDownloadMadeProgress(object sender, AppCastItem item, ItemDownloadProgressEventArgs e)
        {
            await Task.Run(() => {
                if (LastProgressPercentage != e.ProgressPercentage)
                {
                    LastProgressPercentage = e.ProgressPercentage;

                    string DownloadLog = string.Format($"The download made some progress! {e.ProgressPercentage}% done.");
                    SparkleInst.LogWriter.PrintMessage(DownloadLog);

                    if (IsCancelRequested == false)
                    {
                        string DownloadInfo = string.Format($"{item.AppName} {item.Version}<br>The download made some progress! {e.ProgressPercentage}% done.");
                        DownloadUpdate?.UpdateProgress(DownloadInfo, e.ProgressPercentage);
                    }
                    else
                    {
                        if (IsCanceled == false)
                        {
                            IsCanceled = true;
                            Task.Delay(100);
                            DownloadUpdate?.ClosePopUp();
                        }
                    }
                }
            });
        }
示例#6
0
 public async void SkipUpdateClick(AppCastItem CurrentItem)
 {
     await Task.Run(() => {
         CLog.Here().Information($"AppUpdaterService - SkipUpdate : [ {CurrentItem.AppName} {CurrentItem.Version} ]");
         SparkleInst.Configuration.SetVersionToSkip(CurrentItem.Version);
     });
 }
        private async void OnDownloadFinished(AppCastItem item, string path)
        {
            _progressText.Text = Loc.Resolve("updater_dl_progress_finished");

            try
            {
                FileInfo fileInfo = new FileInfo(path);
                fileInfo.DeleteAlternateDataStream("Zone.Identifier");
                fileInfo.MoveTo(Path.Combine(fileInfo.DirectoryName ?? "", "GalaxyBudsClient_Updater.exe"));

                Process proc = new Process
                {
                    StartInfo =
                    {
                        FileName        = Path.Combine(fileInfo.DirectoryName ?? "", "GalaxyBudsClient_Updater.exe"),
                        UseShellExecute = true,
                        Verb            = "runas"
                    }
                };
                proc.Start();
            }
            catch (Exception exception)
            {
                Log.Warning("UpdateProgressPage: Exception raised while launching installer: " + exception.Message + $" ({path})");
            }

            if (BluetoothImpl.Instance.IsConnected)
            {
                await BluetoothImpl.Instance.DisconnectAsync();
            }

            await Task.Delay(400);

            Environment.Exit(0);
        }
示例#8
0
        private void CheckForUpdates(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            Task.Run(async() =>
            {
                var _updateInfo = await _sparkle.CheckForUpdatesQuietly();
                Log.Information($"Update info is {_updateInfo.Status}");
                if (_updateInfo.Status == UpdateStatus.UpdateAvailable)
                {
                    try
                    {
                        LastUpdate        = _updateInfo.Updates.Last();
                        ctx.HasUpdates    = true;
                        ctx.UpdateVersion = LastUpdate.Version;
                        await _sparkle.InitAndBeginDownload(LastUpdate);

                        if (MacUpdater == null)
                        {
                            MacUpdater = new MacUpdater
                            {
                                SignatureVerifier = _sparkle.SignatureVerifier,
                                UpdateDownloader  = _sparkle.UpdateDownloader
                            };
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Error(e.ToString());
                    }
                }
            });
        }
        public NetSparkleUpdateDialog(AppCastItem appCast)
        {
            InitializeComponent();
            if (Application.Current?.MainWindow != null)
            {
                Owner = Application.Current.MainWindow;
            }

            DataContext = this;
            CurrentItem = appCast;

            if (string.IsNullOrEmpty(appCast.ReleaseNotesLink) == false)
            {
                Browser.Navigate(new Uri(appCast.ReleaseNotesLink));
            }
            else if (string.IsNullOrEmpty(appCast.Description) == false)
            {
                Browser.NavigateToString(appCast.Description);
            }

            Description.Content = string.Format(
                Strings.UPDATE_DIALOG_DESCRIPTION,
                Helpers.Resource.Get <string>("BRAND_NAME"),
                CurrentItem.Version,
                CurrentItem.AppVersionInstalled);

            UpdateHeader.Header = string.Format(Strings.UPDATE_DIALOG_HEADER, Helpers.Resource.Get <string>("BRAND_NAME"));
        }
示例#10
0
 public async void CBFullUpdateDownloadFileIsReady(AppCastItem item, string downloadPath)
 {
     await Task.Run(() => {
         // RunFullUpdateUpdateStatusLabel.Text = "Update is ready...";
         string DownloadLog = string.Format($"AppUpdaterService - CBFullUpdateDownloadFileIsReady : [{item.AppName} {item.Version} - Update is ready... [{downloadPath}]]");
         SparkleInst.LogWriter.PrintMessage(DownloadLog);
     });
 }
示例#11
0
 public async void CBFullUpdateStartedDownloading(AppCastItem item, string path)
 {
     await Task.Run(() => {
         // RunFullUpdateUpdateStatusLabel.Text = "Started downloading update...";
         string DownloadLog = string.Format($"AppUpdaterService - CBFullUpdateStartedDownloading : [{item.AppName} {item.Version} - Started downloading update... [{path}]]");
         SparkleInst.LogWriter.PrintMessage(DownloadLog);
     });
 }
        private void OnDownloadFinish(AppCastItem item, string path)
        {
            _downloadPath = path;
            EventArgs    eventArgs    = new EventArgs();
            EventHandler eventHandler = UpdateDownloadFinishedEventHandler;

            eventHandler(this, eventArgs);
        }
        private void OnDownloadMadeProgress(object sender, AppCastItem appCastItem, ItemDownloadProgressEventArgs e)
        {
            UpdateProgressDownloadEventArgs eventArgs = new UpdateProgressDownloadEventArgs();

            eventArgs.AppUpdateProgress = e.ProgressPercentage;
            EventHandler <UpdateProgressDownloadEventArgs> eventHandler = UpdateProgressEventHandler;

            eventHandler(this, eventArgs);
        }
 private void OnDownloadHadError(AppCastItem item, string path, Exception exception)
 {
     MainWindow.Instance.Pager.SwitchPage(Pages.UpdateAvailable);
     new MessageBox
     {
         Title       = Loc.Resolve("updater_dl_fail_title"),
         Description = Loc.Resolve("updater_dl_fail") + exception.Message
     }.ShowDialog(MainWindow.Instance);
 }
        private void OnDownloadError(AppCastItem item, string path, Exception ex)
        {
            UpdateProgressDownloadErrorEventArgs eventArgs = new UpdateProgressDownloadErrorEventArgs();

            eventArgs.ErrorException = ex;
            EventHandler <UpdateProgressDownloadErrorEventArgs> eventHandler = UpdateProgressDownloadErrorEventHandler;

            eventHandler(this, eventArgs);
        }
        private void OnDownloadStart(AppCastItem item, string path)
        {
            UpdateProgressDownloadStartEventArgs eventArgs = new UpdateProgressDownloadStartEventArgs();

            eventArgs.UpdateSize = item.UpdateSize;
            eventArgs.Version    = item.Version;
            EventHandler <UpdateProgressDownloadStartEventArgs> eventHandler = UpdateDownloadStartedEventHandler;

            eventHandler(this, eventArgs);
        }
示例#17
0
        public async void Test(string appcast)
        {
            AppCastItem item = _sparkle.AppCastHandler.GetAvailableUpdates().Where(e => e.DownloadSignature == appcast).FirstOrDefault();
            //         MessageBox.Show(item.DownloadLink, "client code");


            await _sparkle.InitAndBeginDownload(item);

            //    await _sparkle.InstallUpdate(update, _downloadPath);
            //      UserResponded?.Invoke(this, new UpdateResponseEventArgs(UpdateAvailableResult.InstallUpdate, item));
        }
        public void BeginUpdate(AppCastItem update)
        {
            MainWindow.Instance.Pager.SwitchPage(Pages.UpdateProgress);

            _progressText.Text     = Loc.Resolve("updater_dl_progress_prepare");
            _progressSizeText.Text = string.Empty;
            _progress.Value        = 0;
            _progress.Minimum      = 0;
            _progress.Maximum      = 100;
            UpdateManager.Instance.Core.InitAndBeginDownload(update);
        }
示例#19
0
 private void OnInstall_Windows(object?sender, AppCastItem e)
 {
     if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
     {
         MainWindow.Instance.UpdateProgressPage.BeginUpdate(e);
     }
     else
     {
         Log.Warning("UpdatePage: Only x64 Windows builds have updater support. Opening download website for manual installation instead.");
         OpenWebsite("https://github.com/ThePBone/GalaxyBudsClient/releases");
     }
 }
示例#20
0
        public async void CBStartedDownloading(AppCastItem item, string path)
        {
            await Task.Run(() => {
                IsCancelRequested   = false;
                IsCanceled          = false;
                string DownloadLog  = string.Format($"{item.AppName} {item.Version} Started downloading... : [{path}]");
                string DownloadInfo = string.Format($"{item.AppName} {item.Version}<br>Started downloading...");

                SparkleInst.LogWriter.PrintMessage(DownloadLog);
                DownloadUpdate?.OpenPopUp(DownloadInfo);
            });
        }
示例#21
0
 public async void CBDownloadError(AppCastItem item, string path, Exception exception)
 {
     // Display in progress when error occured -> DownloadInfo.Text = "We had an error during the download process :( -- " + exception.Message;
     await Task.Run(() => {
         string DownloadLog = string.Format($"{item.AppName} {item.Version}, We had an error during the download process :( -- {exception.Message}");
         CLog.Here().Error(DownloadLog);
         DownloadUpdate?.ClosePopUp();
         File.Delete(path);
         IsCancelRequested = false;
         IsCanceled        = false;
     });
 }
示例#22
0
        public async void CBDownloadCanceled(AppCastItem item, string path)
        {
            await Task.Run(() => {
                CLog.Here().Information($"AppUpdaterService - CBDownloadCanceled : [ {item.AppName} {item.Version} Cancel downloading! : [{path}] ]");

                if (IsCanceled == false)
                {
                    IsCancelRequested = false;
                    IsCanceled        = true;
                    DownloadUpdate?.ClosePopUp();
                }
            });
        }
示例#23
0
        private void Select(AppCastItem item, bool silent)
        {
            _appcastItem = item;

            if (silent && SettingsProvider.Instance.UpdateSkippedVersion == item.Version)
            {
                Log.Information($"UpdateManager: Ignoring new update {item.Version}; skipped by user");
                return;
            }

            Dispatcher.UIThread.Post(() => _versionTitle.Text = string.Format(Loc.Resolve("updater_newrelease"), item.Version));

            _previousPage = MainWindow.Instance.Pager.CurrentPage;
            MainWindow.Instance.Pager.SwitchPage(Pages.UpdateAvailable);
        }
        public async Task <string> GetDownloadPathForAppCastItem(AppCastItem item)
        {
            if (item != null && item.DownloadLink != null)
            {
                string filename = string.Empty;

                // default to using the server's file name as the download file name
                if (CheckServerFileName && UpdateDownloader != null)
                {
                    try
                    {
                        filename = await UpdateDownloader.RetrieveDestinationFileNameAsync(item);
                    }
                    catch (Exception)
                    {
                        // ignore
                    }
                }

                if (string.IsNullOrEmpty(filename))
                {
                    // attempt to get download file name based on download link
                    try
                    {
                        filename = Path.GetFileName(new Uri(item.DownloadLink).LocalPath);
                    }
                    catch (UriFormatException)
                    {
                        // ignore
                    }
                }

                if (!string.IsNullOrEmpty(filename))
                {
                    string tmpPath = string.IsNullOrEmpty(TmpDownloadFilePath)
                        ? Path.GetTempPath()
                        : TmpDownloadFilePath;

                    // Creates all directories and subdirectories in the specific path unless they already exist.
                    Directory.CreateDirectory(tmpPath);

                    return(Path.Combine(tmpPath, filename));
                }
            }

            return(null);
        }
示例#25
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="item">The appcast item to use</param>
        /// <param name="applicationIcon">Your application Icon</param>
        public DownloadProgressWindow(AppCastItem item, Icon applicationIcon)
        {
            InitializeComponent();

            imgAppIcon.Image = applicationIcon.ToBitmap();
            Icon             = applicationIcon;

            // init ui
            btnInstallAndReLaunch.Visible = false;
            lblHeader.Text           = lblHeader.Text.Replace("APP", item.AppName + " " + item.Version);
            downloadProgressLbl.Text = "";
            progressDownload.Maximum = 100;
            progressDownload.Minimum = 0;
            progressDownload.Step    = 1;

            FormClosing += DownloadProgressWindow_FormClosing;
        }
        private void OnDownloadFinish(AppCastItem item, string path)
        {
            _downloadPath = path;
            UpdateProgressDownloadFinishEventArgs eventArgs = new UpdateProgressDownloadFinishEventArgs();

            if (System.IO.File.Exists(_downloadPath + ".zip"))
            {
                System.IO.File.Delete(_downloadPath + ".zip");
            }

            System.IO.File.Move(_downloadPath, _downloadPath + ".zip");
            string NewFile = _downloadPath + ".zip";

            eventArgs.UpdateFilePath = NewFile;
            eventArgs.castItem       = item;
            EventHandler <UpdateProgressDownloadFinishEventArgs> eventHandler = UpdateDownloadFinishedEventHandler;

            eventHandler(this, eventArgs);
        }
示例#27
0
        public async void CBFinishedDownloading(AppCastItem item, string path)
        {
            await Task.Run(() => {
                if (IsCancelRequested == false)
                {
                    string DownloadLog  = string.Format($"{item.AppName} {item.Version} Done downloading! : [{path}]");
                    string DownloadInfo = string.Format($"{item.AppName} {item.Version}<br>Done downloading!");

                    SparkleInst.LogWriter.PrintMessage(DownloadLog);
                    DownloadUpdate?.UpdateProgress(DownloadInfo, 100);
                    Task.Delay(1000);

                    DownloadUpdate?.ClosePopUp();
                    DownloadPath = path;

                    string FinishedDownloadInfo = string.Format($"{item.AppName} {item.Version}");
                    FinishedDownload?.OpenPopUp(FinishedDownloadInfo);
                }
                else
                {
                    string DownloadLog = string.Format($"{item.AppName} {item.Version} Force Cancel downloading! : [{path}]");
                    SparkleInst.LogWriter.PrintMessage(DownloadLog);

                    string DownloadInfo = string.Format($"{item.AppName} {item.Version}<br>Cancel downloading!");
                    DownloadUpdate?.UpdateProgress(DownloadInfo, 100);
                    Task.Delay(1000);

                    if (IsCanceled == false)
                    {
                        IsCancelRequested = false;
                        IsCanceled        = true;
                        DownloadUpdate?.ClosePopUp();
                        File.Delete(path);
                    }
                }
            });
        }
示例#28
0
        /// <summary>
        /// 更新情報のダウンロード後に呼ばれます。
        /// </summary>
        void web_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {
            if (e.Cancelled || e.Error != null)
            {
                Log.ErrorException(e.Error,
                    "更新情報の取得に失敗しました。");

                this.latestVersionEvent.Set();
                return;
            }

            try
            {
                var text = Encoding.UTF8.GetString(e.Result);
                var latestVersion = AppCastItemUtil.GetLatestVersion(text);
                if (!IsUpdateRequired(latestVersion))
                {
                    this.latestVersionEvent.Set();
                    return;
                }

                this.latestVersion = latestVersion;
                this.latestVersionEvent.Set();

                // show the update window
                Log.Info(
                    "Update needed from version {0} to version {1}.",
                    this.config.InstalledVersion,
                    latestVersion.Version);

                switch (OnUpdateDetected(latestVersion))
                {
                    case NextUpdateAction.ContinueToUpdate:
                        Log.Info("Updater: Continue to update");
                        BeginDownload(latestVersion);
                        break;
                    case NextUpdateAction.ProhibitUpdate:
                    default:
                        Log.Info("Updater: Update prohibited");
                        break;
                }
            }
            catch (Exception ex)
            {
                Log.ErrorException(ex,
                    "ダウンロードに失敗しました。");
            }
        }
 private void OnDownloadCanceled(AppCastItem item, string path)
 {
     Log.Information("UpdateProgressPage: Update cancellation complete");
 }
 private void OnDownloadMadeProgress(object sender, AppCastItem item, ItemDownloadProgressEventArgs args)
 {
     _progressText.Text     = string.Format(Loc.Resolve("updater_dl_progress"), args.ProgressPercentage);
     _progressSizeText.Text = string.Format(Loc.Resolve("updater_dl_progress_size"), (args.BytesReceived / 1000000f).ToString("N2"), (args.TotalBytesToReceive / 1000000f).ToString("N2"));
     _progress.Value        = args.ProgressPercentage;
 }
示例#31
0
        /// <summary>
        /// This method checks if an update is required. During this process the appcast
        /// will be downloaded and checked against the reference assembly. Ensure that
        /// the calling process has access to the internet and read access to the 
        /// reference assembly. This method is also called from the background loops.
        /// </summary>
        private bool IsUpdateRequired(AppCastItem latestVersion)
        {
            if (latestVersion == null)
            {
                Log.Info(
                    "Updater: No version information in app cast found.");
                return false;
            }
            else
            {
                Log.Info(
                    "Updater: Lastest version on the server is {0}.",
                    latestVersion.Version);
            }

            // check if the available update has to be skipped
            if (latestVersion.Version.Equals(this.config.SkipThisVersion))
            {
                Log.Info(
                    "Updater: Latest update has to be skipped (user decided to skip version {0})",
                    config.SkipThisVersion);
                return false;
            }

            // check if the version will be the same then the installed version
            var v1 = new Version(this.config.InstalledVersion);
            var v2 = new Version(latestVersion.Version);

            if (v2 <= v1)
            {
                Log.Info(
                    "Updater: Installed version is valid, no update needed. ({0})",
                    this.config.InstalledVersion);
                return false;
            }

            // ok we need an update
            return true;
        }
示例#32
0
        /// <summary>
        /// 新たな更新情報が確認された後の手続きを確認します。
        /// </summary>
        private NextUpdateAction OnUpdateDetected(AppCastItem latestVersion)
        {
            var e = new UpdateDetectedEventArgs
            {
                NextAction = NextUpdateAction.ContinueToUpdate,
                ApplicationConfig = config,
                LatestVersion = latestVersion,
            };

            UpdateDetected.SafeRaiseEvent(this, e);
            return e.NextAction;
        }
示例#33
0
        /// <summary>
        /// 必要なファイルのダウンロードを開始します。
        /// </summary>
        private void BeginDownload(AppCastItem latestVersion)
        {
            this.downloader = new Downloader();
            this.downloadFilePath = Util.GetTempFileName();
            this.packFilePath = Util.GetTempFileName();
            this.packConfigFilePath = this.packFilePath + ".config";

            this.downloader.BeginDownload(
                new Uri(latestVersion.DownloadLink),
                (_, e) => SaveDownloadFile(this.downloadFilePath, e));
            this.downloader.BeginDownload(
                new Uri(latestVersion.UpdatePackLink),
                (_, e) => SaveDownloadFile(this.packFilePath, e));
            this.downloader.BeginDownload(
                new Uri(latestVersion.UpdatePackLink + ".config"),
                (_, e) => SaveDownloadFile(this.packConfigFilePath, e));
        }
示例#34
0
        /// <summary>
        /// Runs the specified opts.
        /// </summary>
        /// <param name="opts">The opts.</param>
        private static void Run(Options opts)
        {
            // Really really lacks documentation
            _signatureManager.SetStorageDirectory(opts.KeyLocation);

            Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;

            if (opts.Export)
            {
                Console.WriteLine("Private Key:");
                Console.WriteLine(Convert.ToBase64String(_signatureManager.GetPrivateKey()));
                Console.WriteLine("Public Key:");
                Console.WriteLine(Convert.ToBase64String(_signatureManager.GetPublicKey()));
                return;
            }

            if (opts.GenerateKeys)
            {
                var didSucceed = _signatureManager.Generate(opts.ForceRegeneration);
                if (didSucceed)
                {
                    Console.WriteLine("Keys successfully generated", Color.Green);
                }
                else
                {
                    Console.WriteLine("Keys failed to generate", Color.Red);
                }
                return;
            }

            if (opts.BinaryToSign != null)
            {
                var signature = _signatureManager.GetSignatureForFile(new FileInfo(opts.BinaryToSign));

                Console.WriteLine($"Signature: {signature}", Color.Green);

                return;
            }

            if (opts.BinaryToVerify != null)
            {
                var result = _signatureManager.VerifySignature(new FileInfo(opts.BinaryToVerify), opts.Signature);

                if (result)
                {
                    Console.WriteLine($"Signature valid", Color.Green);
                }
                else
                {
                    Console.WriteLine($"Signature invalid", Color.Red);
                }

                return;
            }

            List <string> binaries = new List <string>();

            foreach (var item in opts.Extension.Split(",", StringSplitOptions.RemoveEmptyEntries))
            {
                var search = $"*.{item}";

                if (opts.SourceBinaryDirectory == ".")
                {
                    opts.SourceBinaryDirectory = Environment.CurrentDirectory;
                }

                var files = Directory.GetFiles(opts.SourceBinaryDirectory, search);

                if (files.Length == 0)
                {
                    Console.WriteLine($"No files founds matching {search} in {opts.SourceBinaryDirectory}", Color.Yellow);
                    Environment.Exit(1);
                }
                binaries.AddRange(files);
            }

            var outputDirectory = opts.SourceBinaryDirectory;

            Console.WriteLine("");
            Console.WriteLine($"Searching: {opts.SourceBinaryDirectory}", Color.Blue);
            Console.WriteLine($"Found {binaries.Count()} {opts.Extension} files(s)", Color.Blue);
            Console.WriteLine("");

            try
            {
                var items = new List <AppCastItem>();

                var hasChangelog = File.Exists(opts.ChangeLogPath);

                var verFileInfo      = new FileInfo(Path.Combine(opts.VersionExtractionPath, "IronyModManager.exe"));
                var versionInfo      = GetVersionFromAssembly(verFileInfo);
                var titleVersionInfo = GetTitleVersionFromAssembly(verFileInfo);

                foreach (var binary in binaries)
                {
                    var fileInfo         = new FileInfo(binary);
                    var remoteUpdateFile = $"{opts.BaseUrl}/{(opts.PrefixVersion ? $"v{titleVersionInfo}/" : "")}{HttpUtility.UrlEncode(fileInfo.Name)}";

                    string os = string.Empty;
                    if (binary.Contains("win", StringComparison.OrdinalIgnoreCase))
                    {
                        os = "windows";
                    }
                    else if (binary.Contains("linux", StringComparison.OrdinalIgnoreCase))
                    {
                        os = "linux";
                    }
                    else if (binary.Contains("osx", StringComparison.OrdinalIgnoreCase))
                    {
                        os = "osx";
                    }
                    //
                    var item = new AppCastItem()
                    {
                        Title                 = titleVersionInfo,
                        DownloadLink          = remoteUpdateFile,
                        Version               = versionInfo,
                        ShortVersion          = versionInfo.Substring(0, versionInfo.LastIndexOf('.')),
                        PublicationDate       = fileInfo.CreationTime,
                        UpdateSize            = fileInfo.Length,
                        Description           = "",
                        DownloadSignature     = _signatureManager.KeysExist() ? _signatureManager.GetSignatureForFile(fileInfo) : null,
                        OperatingSystemString = os,
                        MIMEType              = MimeTypes.GetMimeType(fileInfo.Name)
                    };

                    if (hasChangelog)
                    {
                        item.Description = File.ReadAllText(opts.ChangeLogPath);
                    }

                    items.Add(item);
                }

                var appcastXmlDocument = XMLAppCast.GenerateAppCastXml(items, "Irony Mod Manager");

                var appcastFileName = Path.Combine(outputDirectory, opts.AppCastFileName);

                var dirName = Path.GetDirectoryName(appcastFileName);

                if (!Directory.Exists(dirName))
                {
                    Console.WriteLine("Creating {0}", dirName);
                    Directory.CreateDirectory(dirName);
                }

                Console.WriteLine("Writing appcast to {0}", appcastFileName);

                using (var w = XmlWriter.Create(appcastFileName, new XmlWriterSettings {
                    NewLineChars = "\n", Encoding = new UTF8Encoding(false)
                }))
                {
                    appcastXmlDocument.Save(w);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine();
                Environment.Exit(1);
            }
        }
        private bool IsUpdateRequired(AppCastItem latestVersion)
        {
            if (latestVersion == null) return false;

            Version v1 = new Version(InstalledVersion);
            Version v2 = new Version(latestVersion.Version);

            return v2 > v1;
        }
        private void DoUpdate(AppCastItem latestVersion)
        {
            if (latestVersion == null) return;

            string downloadLink = latestVersion.DownloadLink;

            if (!WebFileExist(downloadLink)) return;

            LaunchLiveUpdater(downloadLink, ExecutablePath);

            // close current program
            ShutDown();
        }