コード例 #1
0
        internal static async Task DownloadAndInstallNewVersion(IDispatcherService dispatcher, IDialogService dialogService, string strideInstallerUrl)
        {
            try
            {
                // Diplay progress window
                var mainWindow = dispatcher.Invoke(() => Application.Current.MainWindow as LauncherWindow);
                dispatcher.InvokeAsync(() =>
                {
                    selfUpdateWindow = new SelfUpdateWindow {
                        Owner = mainWindow
                    };
                    selfUpdateWindow.LockWindow();
                    selfUpdateWindow.ShowDialog();
                }).Forget();


                var strideInstaller = Path.Combine(Path.GetTempPath(), $"StrideSetup-{Guid.NewGuid()}.exe");
                using (WebClient webClient = new WebClient())
                {
                    webClient.DownloadFile(strideInstallerUrl, strideInstaller);
                }

                var startInfo = new ProcessStartInfo(strideInstaller)
                {
                    UseShellExecute = true
                };
                // Release the mutex before starting the new process
                Launcher.Mutex.Dispose();

                Process.Start(startInfo);

                Environment.Exit(0);
            }
            catch (Exception e)
            {
                await dispatcher.InvokeAsync(() =>
                {
                    if (selfUpdateWindow != null)
                    {
                        selfUpdateWindow.ForceClose();
                    }
                });

                await dialogService.MessageBox(string.Format(Strings.NewVersionDownloadError, e.Message), MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
コード例 #2
0
        private static async Task UpdateLauncherFiles(IDispatcherService dispatcher, IDialogService dialogService, NugetStore store, CancellationToken cancellationToken)
        {
            var version          = new PackageVersion(Version);
            var productAttribute = (typeof(SelfUpdater).Assembly).GetCustomAttribute <AssemblyProductAttribute>();
            var packageId        = productAttribute.Product;
            var packages         = (await store.GetUpdates(new PackageName(packageId, version), true, true, cancellationToken)).OrderBy(x => x.Version);

            try
            {
                // First, check if there is a package forcing us to download new installer
                const string ReinstallUrlPattern = @"force-reinstall:\s*(\S+)\s*(\S+)";
                var          reinstallPackage    = packages.LastOrDefault(x => x.Version > version && Regex.IsMatch(x.Description, ReinstallUrlPattern));
                if (reinstallPackage != null)
                {
                    var regexMatch     = Regex.Match(reinstallPackage.Description, ReinstallUrlPattern);
                    var minimumVersion = PackageVersion.Parse(regexMatch.Groups[1].Value);
                    if (version < minimumVersion)
                    {
                        var installerDownloadUrl = regexMatch.Groups[2].Value;
                        await DownloadAndInstallNewVersion(dispatcher, dialogService, installerDownloadUrl);

                        return;
                    }
                }
            }
            catch (Exception e)
            {
                await dialogService.MessageBox(string.Format(Strings.NewVersionDownloadError, e.Message), MessageBoxButton.OK, MessageBoxImage.Error);
            }

            // If there is a mandatory intermediate upgrade, take it, otherwise update straight to latest version
            var package = (packages.FirstOrDefault(x => x.Version > version && x.Version.SpecialVersion == "req") ?? packages.LastOrDefault());

            // Check to see if an update is needed
            if (package != null && version < new PackageVersion(package.Version.Version, package.Version.SpecialVersion))
            {
                var windowCreated = new TaskCompletionSource <SelfUpdateWindow>();
                var mainWindow    = dispatcher.Invoke(() => Application.Current.MainWindow as LauncherWindow);
                if (mainWindow == null)
                {
                    throw new ApplicationException("Update requested without a Launcher Window. Cannot continue!");
                }

                dispatcher.InvokeAsync(() =>
                {
                    selfUpdateWindow = new SelfUpdateWindow {
                        Owner = mainWindow
                    };
                    windowCreated.SetResult(selfUpdateWindow);
                    selfUpdateWindow.ShowDialog();
                }).Forget();

                var movedFiles = new List <string>();

                // Download package
                var installedPackage = await store.InstallPackage(package.Id, package.Version, null);

                // Copy files from tools\ to the current directory
                var inputFiles = installedPackage.GetFiles();

                var window = windowCreated.Task.Result;
                dispatcher.Invoke(window.LockWindow);

                // TODO: We should get list of previous files from nuspec (store it as a resource and open it with NuGet API maybe?)
                // TODO: For now, we deal only with the App.config file since we won't be able to fix it afterward.
                var          exeLocation   = Launcher.GetExecutablePath();
                var          exeDirectory  = Path.GetDirectoryName(exeLocation);
                const string directoryRoot = "tools/"; // Important!: this is matching where files are store in the nuspec
                try
                {
                    if (File.Exists(exeLocation))
                    {
                        Move(exeLocation, exeLocation + ".old");
                        movedFiles.Add(exeLocation);
                    }
                    var configLocation = exeLocation + ".config";
                    if (File.Exists(configLocation))
                    {
                        Move(configLocation, configLocation + ".old");
                        movedFiles.Add(configLocation);
                    }
                    foreach (var file in inputFiles.Where(file => file.Path.StartsWith(directoryRoot) && !file.Path.EndsWith("/")))
                    {
                        var fileName = Path.Combine(exeDirectory, file.Path.Substring(directoryRoot.Length));

                        // Move previous files to .old
                        if (File.Exists(fileName))
                        {
                            Move(fileName, fileName + ".old");
                            movedFiles.Add(fileName);
                        }

                        // Update the file
                        UpdateFile(fileName, file);
                    }
                }
                catch (Exception)
                {
                    // Revert all olds files if a file didn't work well
                    foreach (var oldFile in movedFiles)
                    {
                        Move(oldFile + ".old", oldFile);
                    }
                    throw;
                }


                // Remove .old files
                foreach (var oldFile in movedFiles)
                {
                    try
                    {
                        var renamedPath = oldFile + ".old";

                        if (File.Exists(renamedPath))
                        {
                            File.Delete(renamedPath);
                        }
                    }
                    catch (Exception)
                    {
                        // All the files have been replaced, we let it go even if we cannot remove all the old files.
                    }
                }

                // Clean cache from files obtain via package.GetFiles above.
                store.PurgeCache();

                dispatcher.Invoke(RestartApplication);
            }
        }