示例#1
0
        IEnumerable <IAppSetup> findAppSetupsToRun(string appDirectory)
        {
            var allExeFiles = default(FileInfoBase[]);

            try {
                allExeFiles = fileSystem.GetDirectoryInfo(appDirectory).GetFiles("*.exe");
            } catch (UnauthorizedAccessException ex) {
                // NB: This can happen if we run into a MoveFileEx'd directory,
                // where we can't even get the list of files in it.
                log.WarnException("Couldn't search directory for IAppSetups: " + appDirectory, ex);
                throw;
            }

            var locatedAppSetups = allExeFiles
                                   .Select(x => loadAssemblyOrWhine(x.FullName)).Where(x => x != null)
                                   .SelectMany(x => x.GetModules())
                                   .SelectMany(x => {
                try {
                    return(x.GetTypes().Where(y => typeof(IAppSetup).IsAssignableFrom(y)));
                } catch (ReflectionTypeLoadException ex) {
                    log.WarnException("Couldn't load types from module", ex);
                    return(Enumerable.Empty <Type>());
                }
            })
                                   .Select(createInstanceOrWhine).Where(x => x != null)
                                   .ToArray();

            return(locatedAppSetups.Length > 0
                ? locatedAppSetups
                : allExeFiles.Select(x => new DidntFollowInstructionsAppSetup(x.FullName)).ToArray());
        }
示例#2
0
        IObservable <UpdateInfo> checkForUpdate(bool ignoreDeltaUpdates = false, IObserver <int> progress = null)
        {
            IEnumerable <ReleaseEntry> localReleases = Enumerable.Empty <ReleaseEntry>();

            progress = progress ?? new Subject <int>();

            try {
                var file = fileSystem.GetFileInfo(LocalReleaseFile).OpenRead();

                // NB: sr disposes file
                using (var sr = new StreamReader(file, Encoding.UTF8)) {
                    localReleases = ReleaseEntry.ParseReleaseFile(sr.ReadToEnd());
                }
            } catch (Exception ex) {
                // Something has gone wrong, we'll start from scratch.
                log.WarnException("Failed to load local release list", ex);
                initializeClientAppDirectory();
            }

            IObservable <string> releaseFile;

            // Fetch the remote RELEASES file, whether it's a local dir or an
            // HTTP URL
            try {
                if (isHttpUrl(updateUrlOrPath))
                {
                    log.Info("Downloading RELEASES file from {0}", updateUrlOrPath);
                    releaseFile = urlDownloader.DownloadUrl(String.Format("{0}/{1}", updateUrlOrPath, "RELEASES"), progress);
                }
                else
                {
                    log.Info("Reading RELEASES file from {0}", updateUrlOrPath);
                    var fi = fileSystem.GetFileInfo(Path.Combine(updateUrlOrPath, "RELEASES"));

                    using (var sr = new StreamReader(fi.OpenRead(), Encoding.UTF8)) {
                        var text = sr.ReadToEnd();
                        releaseFile = Observable.Return(text);
                    }

                    progress.OnNext(100);
                    progress.OnCompleted();
                }
            } catch (Exception ex) {
                progress.OnCompleted();
                return(Observable.Throw <UpdateInfo>(ex));
            }

            var ret = releaseFile
                      .Select(ReleaseEntry.ParseReleaseFile)
                      .SelectMany(releases => determineUpdateInfo(localReleases, releases, ignoreDeltaUpdates))
                      .PublishLast();

            ret.Connect();
            return(ret);
        }
示例#3
0
        public IObservable <List <string> > ExecuteInstall(string currentAssemblyDir, IPackage bundledPackageMetadata, IObserver <int> progress = null)
        {
            progress = progress ?? new Subject <int>();

            // NB: This bit of code is a bit clever. The binaries that WiX
            // has installed *itself* meets the qualifications for being a
            // Squirrel update directory (a RELEASES file and the corresponding
            // NuGet packages).
            //
            // So, in order to reuse some code and not write the same things
            // twice we're going to "Eigenupdate" from our own directory;
            // UpdateManager will operate in bootstrap mode and create a
            // local directory for us.
            //
            // Then, we create a *new* UpdateManager whose target is the normal
            // update URL - we can then apply delta updates against the bundled
            // NuGet package to get up to vCurrent. The reason we go through
            // this rigamarole is so that developers don't have to rebuild the
            // installer as often (never, technically).

            var updateUsingDeltas =
                executeInstall(currentAssemblyDir, bundledPackageMetadata, progress: progress)
                .ToObservable()
                .ObserveOn(RxApp.DeferredScheduler)
                .Catch <List <string>, Exception>(ex => {
                log.WarnException("Updating using deltas has failed", ex);
                return(executeInstall(currentAssemblyDir, bundledPackageMetadata, true, progress)
                       .ToObservable());
            });

            return(updateUsingDeltas);
        }
示例#4
0
        IEnumerable <IAppSetup> findAppSetupsToRun(string appDirectory)
        {
            var allExeFiles = default(FileInfoBase[]);

            try {
                allExeFiles = fileSystem.GetDirectoryInfo(appDirectory).GetFiles("*.exe");
            } catch (UnauthorizedAccessException ex) {
                // NB: This can happen if we run into a MoveFileEx'd directory,
                // where we can't even get the list of files in it.
                log.WarnException("Couldn't search directory for IAppSetups: " + appDirectory, ex);
                return(Enumerable.Empty <IAppSetup>());
            }

            var locatedAppSetups = allExeFiles
                                   .Select(x => loadAssemblyOrWhine(x.FullName)).Where(x => x != null)
                                   .SelectMany(x => x.GetModules())
                                   .SelectMany(x => {
                try {
                    return(x.GetTypes().Where(y => typeof(IAppSetup).IsAssignableFrom(y)));
                } catch (ReflectionTypeLoadException ex) {
                    var message = String.Format("Couldn't load types from module {0}", x.FullyQualifiedName);
                    log.WarnException(message, ex);
                    ex.LoaderExceptions.ForEach(le => log.WarnException("LoaderException found", le));
                    return(Enumerable.Empty <Type>());
                }
            })
                                   .Select(createInstanceOrWhine).Where(x => x != null)
                                   .ToArray();

            if (!locatedAppSetups.Any())
            {
                log.Warn("Could not find any AppSetup instances");
                allExeFiles.ForEach(f => log.Info("We have an exe: {0}", f.FullName));
                return(allExeFiles.Select(x => new DidntFollowInstructionsAppSetup(x.FullName))
                       .ToArray());
            }
            return(locatedAppSetups);
        }
示例#5
0
        IObservable <UpdateInfo> checkForUpdate(bool ignoreDeltaUpdates = false, IObserver <int> progress = null)
        {
            var localReleases = Enumerable.Empty <ReleaseEntry>();

            progress = progress ?? new Subject <int>();

            try {
                var file = fileSystem.GetFileInfo(LocalReleaseFile).OpenRead();

                // NB: sr disposes file
                using (var sr = new StreamReader(file, Encoding.UTF8)) {
                    localReleases = ReleaseEntry.ParseReleaseFile(sr.ReadToEnd());
                }
            } catch (Exception ex) {
                // Something has gone wrong, we'll start from scratch.
                log.WarnException("Failed to load local release list", ex);
                initializeClientAppDirectory();
            }

            IObservable <string> releaseFile;

            // Fetch the remote RELEASES file, whether it's a local dir or an
            // HTTP URL
            try {
                if (isHttpUrl(updateUrlOrPath))
                {
                    log.Info("Downloading RELEASES file from {0}", updateUrlOrPath);
                    releaseFile = urlDownloader.DownloadUrl(String.Format("{0}/{1}", updateUrlOrPath, "RELEASES"), progress)
                                  .Catch <string, TimeoutException>(ex => {
                        log.Info("Download timed out (returning blank release list)");
                        return(Observable.Return(String.Empty));
                    })
                                  .Catch <string, WebException>(ex => {
                        log.InfoException("Download resulted in WebException (returning blank release list)", ex);
                        return(Observable.Return(String.Empty));
                    });
                }
                else
                {
                    log.Info("Reading RELEASES file from {0}", updateUrlOrPath);

                    if (!fileSystem.GetDirectoryInfo(updateUrlOrPath).Exists)
                    {
                        var message =
                            String.Format(
                                "The directory {0} does not exist, something is probably broken with your application", updateUrlOrPath);
                        var ex = new SquirrelConfigurationException(message);
                        return(Observable.Throw <UpdateInfo>(ex));
                    }

                    var fi = fileSystem.GetFileInfo(Path.Combine(updateUrlOrPath, "RELEASES"));
                    if (!fi.Exists)
                    {
                        var message = String.Format(
                            "The file {0} does not exist, something is probably broken with your application", fi.FullName);

                        log.Warn(message);

                        var packages = fileSystem.GetDirectoryInfo(updateUrlOrPath).GetFiles("*.nupkg");
                        if (packages.Length == 0)
                        {
                            var ex = new SquirrelConfigurationException(message);
                            return(Observable.Throw <UpdateInfo>(ex));
                        }

                        // NB: Create a new RELEASES file since we've got a directory of packages
                        ReleaseEntry.WriteReleaseFile(
                            packages.Select(x => ReleaseEntry.GenerateFromFile(x.FullName)), fi.FullName);
                    }

                    using (var sr = new StreamReader(fi.OpenRead(), Encoding.UTF8)) {
                        var text = sr.ReadToEnd();
                        releaseFile = Observable.Return(text);
                    }

                    progress.OnNext(100);
                    progress.OnCompleted();
                }
            } catch (Exception ex) {
                progress.OnCompleted();
                return(Observable.Throw <UpdateInfo>(ex));
            }

            // Return null if no updates found
            var ret = releaseFile
                      .Select(ReleaseEntry.ParseReleaseFile)
                      .SelectMany(releases =>
                                  releases.Any() ? determineUpdateInfo(localReleases, releases, ignoreDeltaUpdates)
                        : Observable.Return <UpdateInfo>(null))
                      .PublishLast();

            ret.Connect();
            return(ret);
        }