Exemple #1
0
 // Install a package
 public void InstallPackage(IPackage package, Action onComplete = null)
 {
     downloadThreads.Add(RunThread(() =>
     {
         if (!isSafeToProcess())
         {
             return;
         }
         Info("Preparing Installation");
         OnProcessing();
         IsDownloading = true;
         try
         {
             store.InstallPackage(package.Id, package.Version);
         }
         catch (Exception)
         {
             ShowErrorDialog("Could not retrieve package!");
         }
         IsDownloading = false;
         SdkVersionManager.synchronizeData();
         OnSDKVersionsUpdated();
         Info("");
         OnIdle();
         if (onComplete != null)
         {
             onComplete();
         }
     }));
 }
Exemple #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);
            }
        }
Exemple #3
0
        public int Run(string[] args)
        {
            // Start self update
            downloadThreads.Add(RunThread(SelfUpdate));
            DebugStep("SelfUpdate launched");

            // Find locally installed package
            var installedPackage = FindLatestInstalledPackage(store.Manager.LocalRepository);

            DebugStep("Find installed package");

            // Do we have a package in the cache?
            var cachePackage = FindLatestInstalledPackage(MachineCache.Default);

            DebugStep("Find cache package");

            // If a package is installed
            if (installedPackage != null)
            {
                if (cachePackage != null && cachePackage.Version > installedPackage.Version)
                {
                    var  processCount   = GetProcessCount();
                    bool isSafeToUpdate = processCount <= 1;

                    // If we are safe to update, install the new package
                    if (isSafeToUpdate)
                    {
                        IsDownloading = true;
                        Info("Preparing installer for new {0} version {1}", mainPackage, cachePackage.Version);
                        PackageUpdate(installedPackage, false);
                        IsDownloading = false;
                        DebugStep("Update package");
                    }
                    else
                    {
                        ShowInformationDialog(
                            string.Format("Cannot update {0} as there are [{1}] instances currently running.\n\nClose all your applications and restart", mainPackage, processCount));
                    }
                }
                else
                {
                    DebugStep("Start download package in cache");

                    var localPackage = installedPackage;
                    downloadThreads.Add(RunThread(() => PackageUpdate(localPackage, true)));
                }
            }
            else
            {
                if (store.CheckSource())
                {
                    //store.Manager.InstallPackage(mainPackage);
                    IsDownloading = true;
                    Info("Preparing installer for {0}", mainPackage);

                    store.InstallPackage(mainPackage, null);

                    IsDownloading = false;
                    DebugStep("Package installed");
                }
                else
                {
                    ShowErrorDialog("Download server not available. Please try again later");
                    return(1);
                }
            }

            installedPackage = FindLatestInstalledPackage(store.Manager.LocalRepository);

            if (installedPackage == null)
            {
                ShowErrorDialog("No package installed");
                return(1);
            }

            // Load the assembly and call the default entry point:
            var fullExePath = GetMainExecutable(installedPackage);

            Environment.CurrentDirectory = Path.GetDirectoryName(fullExePath);
            var appDomainSetup = new AppDomainSetup {
                ApplicationBase = Path.GetDirectoryName(fullExePath)
            };
            var newAppDomain = AppDomain.CreateDomain("LauncherAppDomain", null, appDomainSetup);

            DebugStep("Run executable");
            OnLoading(new LoadingEventArgs(installedPackage.Id, installedPackage.Version.ToString()));

            var newArgList = new List <string> {
                "/LauncherWindowHandle", MainWindowHandle.ToInt64().ToString(CultureInfo.InvariantCulture)
            };

            newArgList.AddRange(args);

            try
            {
                return(newAppDomain.ExecuteAssembly(fullExePath, newArgList.ToArray()));
            }
            finally
            {
                // Important!: Force back current directory to this application as previous ExecuteAssembly is changing it
                Environment.CurrentDirectory = Path.GetDirectoryName(typeof(LauncherApp).Assembly.Location);

                // Note: The AppDomain.Unload method can block indefinitely when a crash occurs in the UI
                //try
                //{
                //    AppDomain.Unload(newAppDomain);
                //}
                //catch (Exception)
                //{
                //}
            }
        }
Exemple #4
0
        public async Task CheckDeveloperTargetRedirects(string id, PackageVersion version, string realPath)
        {
            var nupkgFile = Path.Combine(Environment.ExpandEnvironmentVariables(store.DevSource), $"{id}.{version}.nupkg");

            var isRedirectToCurrentPath = false;
            var installedPackage        = store.GetLocalPackages(id).FirstOrDefault(x => x.Version == version);

            if (installedPackage != null)
            {
                var redirectFile = Path.Combine(installedPackage.Path, $@"{id}.redirect");
                if (File.Exists(redirectFile) && String.Compare(File.ReadAllText(redirectFile), realPath, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    isRedirectToCurrentPath = true;
                }
            }

            // Note: later, we could do better and check existing package contents and scan for differences?
            // We could also delete older packages using same path
            if (File.Exists(nupkgFile) && isRedirectToCurrentPath)
            {
                return;
            }

            Directory.CreateDirectory(Path.GetDirectoryName(nupkgFile));

            var builder = new NugetPackageBuilder();
            var meta    = new PackageMeta
            {
                Name        = id,
                Version     = version,
                Authors     = { $"{id} developers" },
                Description = $"{id} developer package using {realPath}",
            };
            var nugetMeta = new ManifestMetadata();

            ToNugetManifest(meta, nugetMeta);

            builder.Populate(nugetMeta);
            // Note: path must exist (created in NugetStore ctor)
            using (var tempDirectory = new TemporaryDirectory())
            {
                // Generate fake files
                Directory.CreateDirectory(Path.Combine(tempDirectory.DirectoryPath, "build"));
                var files = new List <ManifestFile>();
                foreach (var buildFileExtension in new[] { "targets", "props" })
                {
                    var source = Path.Combine(tempDirectory.DirectoryPath, $@"build\{id}.{buildFileExtension}");
                    File.WriteAllText(source, $@"<?xml version=""1.0"" encoding=""utf-8"" ?>
<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" >
  <Import Project=""{realPath}\Targets\Xenko.{buildFileExtension}"" />
</Project>
");
                    files.Add(new ManifestFile {
                        Source = source, Target = $@"build\{id}.{buildFileExtension}"
                    });
                }

                var redirectFile = Path.Combine(tempDirectory.DirectoryPath, $"{id}.redirect");
                File.WriteAllText(redirectFile, realPath);
                files.Add(new ManifestFile {
                    Source = redirectFile, Target = $@"{id}.redirect"
                });

                builder.PopulateFiles(".", files);
                using (var nupkgStream = File.OpenWrite(nupkgFile))
                {
                    builder.Save(nupkgStream);
                }
            }

            // If package is already installed in cache so that it will force reinstallation.
            if (installedPackage != null)
            {
                await store.UninstallPackage(installedPackage, null);
            }

            await store.InstallPackage(id, version, null);
        }