示例#1
0
            async Task <string> installPackageToAppDir(UpdateInfo updateInfo, ReleaseEntry release)
            {
                var pkg    = new ZipPackage(Path.Combine(updateInfo.PackageDirectory, release.Filename));
                var target = getDirectoryForRelease(release.Version);

                // NB: This might happen if we got killed partially through applying the release
                if (target.Exists)
                {
                    this.Log().Warn("Found partially applied release folder, killing it: " + target.FullName);
                    await Utility.DeleteDirectory(target.FullName);
                }

                target.Create();

                // Copy all of the files out of the lib/ dirs in the NuGet package
                // into our target App directory.
                //
                // NB: We sort this list in order to guarantee that if a Net20
                // and a Net40 version of a DLL get shipped, we always end up
                // with the 4.0 version.
                this.Log().Info("Writing files to app directory: {0}", target.FullName);

                var toWrite = pkg.GetLibFiles().Where(x => pathIsInFrameworkProfile(x, appFrameworkVersion))
                              .OrderBy(x => x.Path)
                              .ToList();

                // NB: Because of the above NB, we cannot use ForEachAsync here, we
                // have to copy these files in-order. Once we fix assembly resolution,
                // we can kill both of these NBs.
                await Task.Run(() => toWrite.ForEach(x => copyFileToLocation(target, x)));

                await pkg.GetContentFiles().ForEachAsync(x => copyFileToLocation(target, x));

                return(target.FullName);
            }
示例#2
0
 public static async Task DeleteDirectoryOrJustGiveUp(string dir)
 {
     try {
         await Utility.DeleteDirectory(dir);
     } catch {
         var message = String.Format("Uninstall failed to delete dir '{0}'", dir);
     }
 }
示例#3
0
        public static async Task DeleteDirectoryWithFallbackToNextReboot(string dir)
        {
            try {
                await Utility.DeleteDirectory(dir);
            } catch (Exception ex) {
                var message = String.Format("Uninstall failed to delete dir '{0}', punting to next reboot", dir);
                LogHost.Default.WarnException(message, ex);

                Utility.DeleteDirectoryAtNextReboot(dir);
            }
        }
示例#4
0
            async Task initializeClientAppDirectory()
            {
                // On bootstrap, we won't have any of our directories, create them
                var pkgDir = Path.Combine(rootAppDirectory, "packages");

                if (Directory.Exists(pkgDir))
                {
                    await Utility.DeleteDirectory(pkgDir);
                }

                Directory.CreateDirectory(pkgDir);
            }
            Task <string> installPackageToAppDir(UpdateInfo updateInfo, ReleaseEntry release)
            {
                return(Task.Run(async() => {
                    var zipper = new FastZip();
                    var target = getDirectoryForRelease(release.Version);

                    // NB: This might happen if we got killed partially through applying the release
                    if (target.Exists)
                    {
                        this.Log().Warn("Found partially applied release folder, killing it: " + target.FullName);
                        await Utility.DeleteDirectory(target.FullName);
                    }

                    target.Create();

                    this.Log().Info("Writing files to app directory: {0}", target.FullName);
                    zipper.ExtractZip(
                        Path.Combine(updateInfo.PackageDirectory, release.Filename),
                        target.FullName, FastZip.Overwrite.Always, (o) => true, null, @"lib", true);

                    // Move all of the files out of the lib/ dirs in the NuGet package
                    // into our target App directory.
                    //
                    // NB: We sort this list in order to guarantee that if a Net20
                    // and a Net40 version of a DLL get shipped, we always end up
                    // with the 4.0 version.
                    var libDir = target.GetDirectories().First(x => x.Name.Equals("lib", StringComparison.OrdinalIgnoreCase));
                    var toMove = libDir.GetDirectories().OrderBy(x => x.Name);

                    toMove.ForEach(ld => {
                        ld.GetDirectories()
                        .ForEachAsync(subdir => subdir.MoveTo(subdir.FullName.Replace(ld.FullName, target.FullName)))
                        .Wait();

                        ld.GetFiles()
                        .ForEachAsync(file => {
                            var tgt = Path.Combine(target.FullName, file.Name);
                            this.Log().Info("Moving file {0} to {1}", file.FullName, tgt);
                            if (File.Exists(tgt))
                            {
                                Utility.DeleteFileHarder(tgt, true);
                            }
                            file.MoveTo(tgt);
                        })
                        .Wait();
                    });

                    await Utility.DeleteDirectory(libDir.FullName);
                    return target.FullName;
                }));
            }
            Task <string> installPackageToAppDir(UpdateInfo updateInfo, ReleaseEntry release, Action <int> progressCallback)
            {
                return(Task.Run(async() => {
                    var target = getDirectoryForRelease(release.Version);

                    // NB: This might happen if we got killed partially through applying the release
                    if (target.Exists)
                    {
                        this.Log().Warn("Found partially applied release folder, killing it: " + target.FullName);
                        await Utility.DeleteDirectory(target.FullName);
                    }

                    target.Create();
                    try
                    {
                        this.Log().Info("Writing files to app directory: {0}", target.FullName);
                        await ReleasePackage.ExtractZipForInstall(
                            Path.Combine(updateInfo.PackageDirectory, release.Filename),
                            target.FullName,
                            rootAppDirectory,
                            progressCallback);
                    }
                    catch (Exception ex)
                    {
                        try
                        {
                            //Don't leave that empty directory there: its existence will prevent the user from even using the previous version.
                            await Utility.DeleteDirectory(target.FullName);
                        }
                        catch (Exception error)
                        {
                            //This is going to be one very stuck user...
                            this.Log().ErrorException("Failed to cleanup new directory after failed install: " + target.FullName, error);
                        }
                        throw ex;
                    }

                    return target.FullName;
                }));
            }
示例#7
0
            Task <string> installPackageToAppDir(UpdateInfo updateInfo, ReleaseEntry release)
            {
                return(Task.Run(async() => {
                    var target = getDirectoryForRelease(release.Version);

                    // NB: This might happen if we got killed partially through applying the release
                    if (target.Exists)
                    {
                        this.Log().Warn("Found partially applied release folder, killing it: " + target.FullName);
                        await Utility.DeleteDirectory(target.FullName);
                    }

                    target.Create();

                    this.Log().Info("Writing files to app directory: {0}", target.FullName);
                    await ReleasePackage.ExtractZipForInstall(
                        Path.Combine(updateInfo.PackageDirectory, release.Filename),
                        target.FullName);

                    return target.FullName;
                }));
            }
            public async Task FullUninstall()
            {
                var currentRelease = getReleases().MaxBy(x => x.Name.ToSemanticVersion()).FirstOrDefault();

                this.Log().Info("Starting full uninstall");
                if (currentRelease.Exists)
                {
                    var version = currentRelease.Name.ToSemanticVersion();

                    try {
                        var squirrelAwareApps = SquirrelAwareExecutableDetector.GetAllSquirrelAwareApps(currentRelease.FullName);

                        if (isAppFolderDead(currentRelease.FullName))
                        {
                            throw new Exception("App folder is dead, but we're trying to uninstall it?");
                        }

                        var allApps = currentRelease.EnumerateFiles()
                                      .Where(x => x.Name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
                                      .Where(x => !x.Name.StartsWith("squirrel.", StringComparison.OrdinalIgnoreCase) && !x.Name.StartsWith("update.", StringComparison.OrdinalIgnoreCase))
                                      .ToList();

                        if (squirrelAwareApps.Count > 0)
                        {
                            await squirrelAwareApps.ForEachAsync(async exe => {
                                using (var cts = new CancellationTokenSource()) {
                                    cts.CancelAfter(10 * 1000);

                                    try {
                                        await Utility.InvokeProcessAsync(exe, String.Format("--squirrel-uninstall {0}", version), cts.Token);
                                    } catch (Exception ex) {
                                        this.Log().ErrorException("Failed to run cleanup hook, continuing: " + exe, ex);
                                    }
                                }
                            }, 1 /*at a time*/);
                        }
                        else
                        {
                            allApps.ForEach(x => RemoveShortcutsForExecutable(x.Name, ShortcutLocations.Defaults));
                        }

                        // NB: Some people attempt to uninstall apps while
                        // they're still running. I cannot even.
                        var toKill = allApps
                                     .SelectMany(x => Process.GetProcessesByName(x.Name.Replace(".exe", "")))
                                     .ToList();

                        if (toKill.Count > 0)
                        {
                            toKill.ForEach(x => x.Kill());
                            Thread.Sleep(750);
                        }
                    } catch (Exception ex) {
                        this.Log().WarnException("Failed to run pre-uninstall hooks, uninstalling anyways", ex);
                    }
                }

                fixPinnedExecutables(new SemanticVersion(255, 255, 255, 255));

                bool      didSucceedDeleting = false;
                const int retryAttempts      = 10;

                for (int i = 0; i < retryAttempts; ++i)
                {
                    try {
                        await Utility.DeleteDirectory(rootAppDirectory);

                        didSucceedDeleting = true;
                    } catch (Exception) {
                        Thread.Sleep(1000); // Give the OS a second to release handles and we'll try again
                    }
                }

                if (!didSucceedDeleting)
                {
                    await this.ErrorIfThrows(() => Utility.DeleteDirectoryOrJustGiveUp(rootAppDirectory),
                                             "Failed to delete app directory: " + rootAppDirectory);
                }

                // NB: We drop this file here so that --checkInstall will ignore
                // this folder - if we don't do this, users who "accidentally" run as
                // administrator will find the app reinstalling itself on every
                // reboot
                File.WriteAllText(Path.Combine(rootAppDirectory, ".dead"), " ");
            }
示例#9
0
            Task <string> installPackageToAppDir(UpdateInfo updateInfo, ReleaseEntry release, Action <int> progress)
            {
                return(Task.Run(async() =>
                {
                    var target = getDirectoryForRelease(release.Version);

                    // NB: This might happen if we got killed partially through applying the release
                    if (target.Exists)
                    {
                        this.Log().Warn("Found partially applied release folder, killing it: " + target.FullName);
                        await Utility.DeleteDirectory(target.FullName);
                    }

                    target.Create();

                    var totalSize = GetTotalUncompressedSize(updateInfo, release);
                    var currentExtractedSize = 0L;
                    using (var stream = File.OpenRead(Path.Combine(updateInfo.PackageDirectory, release.Filename)))
                    {
                        // progress.Report(new InstallerStep("Extracting"));

                        var zipIn = new ZipInputStream(stream);
                        var zipEntry = zipIn.GetNextEntry();

                        while (zipEntry != null)
                        {
                            var entryName = zipEntry.Name;
                            var pathParts = entryName.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);

                            var foundLib = false;
                            foreach (var part in pathParts)
                            {
                                if (part.Equals("lib", StringComparison.InvariantCulture))
                                {
                                    foundLib = true;
                                }
                            }

                            if (!foundLib)
                            {
                                zipEntry = zipIn.GetNextEntry();
                                continue;
                            }

                            var buffer = new byte[4096];
                            var fullZipToPath = Path.Combine(target.FullName, entryName.Replace('/', Path.DirectorySeparatorChar));
                            var directoryName = zipEntry.IsFile ? Path.GetDirectoryName(fullZipToPath) : fullZipToPath;
                            if (!string.IsNullOrEmpty(directoryName))
                            {
                                Directory.CreateDirectory(directoryName);
                            }

                            using (var streamWriter = File.Create(fullZipToPath))
                            {
                                currentExtractedSize += zipEntry.Size;
                                StreamUtils.Copy(zipIn, streamWriter, buffer);
                                progress((int)((double)currentExtractedSize * 100.0 / (double)totalSize));
                            }

                            zipEntry = zipIn.GetNextEntry();
                        }
                    }

                    this.Log().Info("Writing files to app directory: {0}", target.FullName);

                    // Move all of the files out of the lib/ dirs in the NuGet package
                    // into our target App directory.
                    //
                    // NB: We sort this list in order to guarantee that if a Net20
                    // and a Net40 version of a DLL get shipped, we always end up
                    // with the 4.0 version.
                    var libDir = target.GetDirectories().First(x => x.Name.Equals("lib", StringComparison.OrdinalIgnoreCase));
                    var toMove = libDir.GetDirectories().OrderBy(x => x.Name);

                    toMove.ForEach(ld => {
                        ld.GetDirectories()
                        .ForEachAsync(subdir => subdir.MoveTo(subdir.FullName.Replace(ld.FullName, target.FullName)))
                        .Wait();

                        ld.GetFiles()
                        .ForEachAsync(file => {
                            var tgt = Path.Combine(target.FullName, file.Name);
                            this.Log().Info("Moving file {0} to {1}", file.FullName, tgt);
                            if (File.Exists(tgt))
                            {
                                Utility.DeleteFileHarder(tgt, true);
                            }
                            file.MoveTo(tgt);
                        })
                        .Wait();
                    });

                    await Utility.DeleteDirectory(libDir.FullName);
                    return target.FullName;
                }));
            }