public void RemoveShortcutsForExecutable(string exeName, ShortcutLocation locations)
            {
                var releases    = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
                var thisRelease = Utility.FindCurrentVersion(releases);

                var zf = new ZipPackage(Path.Combine(
                                            Utility.PackageDirectoryForAppDir(rootAppDirectory),
                                            thisRelease.Filename));

                var fileVerInfo = FileVersionInfo.GetVersionInfo(
                    Path.Combine(Utility.AppDirForRelease(rootAppDirectory, thisRelease), exeName));

                foreach (var f in (ShortcutLocation[])Enum.GetValues(typeof(ShortcutLocation)))
                {
                    if (!locations.HasFlag(f))
                    {
                        continue;
                    }

                    var file = linkTargetForVersionInfo(f, zf, fileVerInfo);

                    this.Log().Info("Removing shortcut for {0} => {1}", exeName, file);

                    this.ErrorIfThrows(() => {
                        if (File.Exists(file))
                        {
                            File.Delete(file);
                        }
                    }, "Couldn't delete shortcut: " + file);
                }

                fixPinnedExecutables(zf.Version);
            }
            public void CreateShortcutsForExecutable(string exeName, ShortcutLocation locations, bool updateOnly)
            {
                var releases    = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
                var thisRelease = Utility.FindCurrentVersion(releases);

                var zf = new ZipPackage(Path.Combine(
                                            Utility.PackageDirectoryForAppDir(rootAppDirectory),
                                            thisRelease.Filename));

                var exePath     = Path.Combine(Utility.AppDirForRelease(rootAppDirectory, thisRelease), exeName);
                var fileVerInfo = FileVersionInfo.GetVersionInfo(exePath);

                foreach (var f in (ShortcutLocation[])Enum.GetValues(typeof(ShortcutLocation)))
                {
                    if (!locations.HasFlag(f))
                    {
                        continue;
                    }

                    var file       = linkTargetForVersionInfo(f, zf, fileVerInfo);
                    var fileExists = File.Exists(file);

                    // NB: If we've already installed the app, but the shortcut
                    // is no longer there, we have to assume that the user didn't
                    // want it there and explicitly deleted it, so we shouldn't
                    // annoy them by recreating it.
                    if (!fileExists && updateOnly)
                    {
                        this.Log().Warn("Wanted to update shortcut {0} but it appears user deleted it", file);
                        continue;
                    }

                    this.Log().Info("Creating shortcut for {0} => {1}", exeName, file);

                    this.ErrorIfThrows(() => {
                        if (fileExists)
                        {
                            File.Delete(file);
                        }

                        var sl = new ShellLink {
                            Target           = exePath,
                            IconPath         = exePath,
                            IconIndex        = 0,
                            WorkingDirectory = Path.GetDirectoryName(exePath),
                            Description      = zf.Description,
                        };

                        this.Log().Info("About to save shortcut: {0}", file);
                        if (ModeDetector.InUnitTestRunner() == false)
                        {
                            sl.Save(file);
                        }
                    }, "Can't write shortcut: " + file);
                }
            }
Exemple #3
0
            private static string GetExePath(string rootAppDirectory, string exeName, ReleaseEntry thisRelease)
            {
                var releaseDir = Utility.AppDirForRelease(rootAppDirectory, thisRelease);
                var exePath    = Path.Combine(releaseDir, exeName);

                if (!File.Exists(exePath))
                {
                    var matches = Directory.GetFiles(releaseDir, exeName, SearchOption.AllDirectories);
                    exePath = matches.FirstOrDefault() ?? exePath;
                }
                return(exePath);
            }
            public Dictionary <ShortcutLocation, ShellLink> GetShortcutsForExecutable(string exeName, ShortcutLocation locations, string programArguments)
            {
                this.Log().Info("About to create shortcuts for {0}, rootAppDir {1}", exeName, rootAppDirectory);

                var releases    = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
                var thisRelease = Utility.FindCurrentVersion(releases);

                var zf = new ZipPackage(Path.Combine(
                                            Utility.PackageDirectoryForAppDir(rootAppDirectory),
                                            thisRelease.Filename));

                var exePath     = Path.Combine(Utility.AppDirForRelease(rootAppDirectory, thisRelease), exeName);
                var fileVerInfo = FileVersionInfo.GetVersionInfo(exePath);

                var ret = new Dictionary <ShortcutLocation, ShellLink>();

                foreach (var f in (ShortcutLocation[])Enum.GetValues(typeof(ShortcutLocation)))
                {
                    if (!locations.HasFlag(f))
                    {
                        continue;
                    }

                    var file                 = linkTargetForVersionInfo(f, zf, fileVerInfo);
                    var appUserModelId       = String.Format("com.squirrel.{0}.{1}", zf.Id.Replace(" ", ""), exeName.Replace(".exe", "").Replace(" ", ""));
                    var toastActivatorCLSDID = Utility.CreateGuidFromHash(appUserModelId).ToString();

                    this.Log().Info("Creating shortcut for {0} => {1}", exeName, file);
                    this.Log().Info("appUserModelId: {0} | toastActivatorCLSID: {1}", appUserModelId, toastActivatorCLSDID);

                    var target = Path.Combine(rootAppDirectory, exeName);
                    var sl     = new ShellLink
                    {
                        Target           = target,
                        IconPath         = target,
                        IconIndex        = 0,
                        WorkingDirectory = Path.GetDirectoryName(exePath),
                        Description      = zf.Description,
                    };

                    if (!String.IsNullOrWhiteSpace(programArguments))
                    {
                        sl.Arguments += String.Format(" -a \"{0}\"", programArguments);
                    }

                    sl.SetAppUserModelId(appUserModelId);
                    sl.SetToastActivatorCLSID(toastActivatorCLSDID);

                    ret.Add(f, sl);
                }

                return(ret);
            }
Exemple #5
0
            public Dictionary <ShortcutLocation, ShellLink> GetShortcutsForExecutable(string exeName, ShortcutLocation locations, string programArguments)
            {
                this.Log().Info("About to create shortcuts for {0}, rootAppDir {1}", exeName, rootAppDirectory);

                var releases    = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
                var thisRelease = Utility.FindCurrentVersion(releases);
                var updateExe   = Path.Combine(rootAppDirectory, "update.exe");

                var zf = new ZipPackage(Path.Combine(
                                            Utility.PackageDirectoryForAppDir(rootAppDirectory),
                                            thisRelease.Filename));

                var exePath     = Path.Combine(Utility.AppDirForRelease(rootAppDirectory, thisRelease), exeName);
                var fileVerInfo = FileVersionInfo.GetVersionInfo(exePath);

                var ret = new Dictionary <ShortcutLocation, ShellLink>();

                foreach (var f in (ShortcutLocation[])Enum.GetValues(typeof(ShortcutLocation)))
                {
                    if (!locations.HasFlag(f))
                    {
                        continue;
                    }

                    var file = linkTargetForVersionInfo(f, zf, fileVerInfo);

                    this.Log().Info("Creating shortcut for {0} => {1}", exeName, file);

                    ShellLink sl;
                    sl = new ShellLink {
                        Target           = updateExe,
                        IconPath         = exePath,
                        IconIndex        = 0,
                        WorkingDirectory = Path.GetDirectoryName(exePath),
                        Description      = zf.Description,
                        Arguments        = "--processStart " + exeName,
                    };

                    if (!String.IsNullOrWhiteSpace(programArguments))
                    {
                        sl.Arguments += String.Format(" -a \"{0}\"", programArguments);
                    }

                    sl.SetAppUserModelId(String.Format("com.squirrel.{0}.{1}", zf.Id, exeName.Replace(".exe", "")));
                    sl.SetAppUserModelRelaunchCommand(String.Format("{0} {1}", sl.Target, sl.Arguments));
                    ret.Add(f, sl);
                }

                return(ret);
            }
            public async Task <string> ApplyReleases(UpdateInfo updateInfo, bool silentInstall, bool attemptingFullInstall, Action <int> progress = null)
            {
                progress = progress ?? (_ => { });

                progress(0);
                var release = await createFullPackagesFromDeltas(updateInfo.ReleasesToApply, updateInfo.CurrentlyInstalledVersion);

                progress(10);

                if (release == null)
                {
                    if (attemptingFullInstall)
                    {
                        this.Log().Info("No release to install, running the app");
                        await invokePostInstall(updateInfo.CurrentlyInstalledVersion.Version, false, true, silentInstall);
                    }

                    progress(100);
                    return(getDirectoryForRelease(updateInfo.CurrentlyInstalledVersion.Version).FullName);
                }

                var ret = await this.ErrorIfThrows(() => installPackageToAppDir(updateInfo, release),
                                                   "Failed to install package to app dir");

                progress(30);

                var currentReleases = await this.ErrorIfThrows(() => updateLocalReleasesFile(),
                                                               "Failed to update local releases file");

                progress(50);

                var newVersion = currentReleases.MaxBy(x => x.Version).First().Version;

                executeSelfUpdate(newVersion);

                await this.ErrorIfThrows(() => invokePostInstall(newVersion, attemptingFullInstall, false, silentInstall),
                                         "Failed to invoke post-install");

                progress(75);

                this.Log().Info("Starting fixPinnedExecutables");
                this.ErrorIfThrows(() => fixPinnedExecutables(updateInfo.FutureReleaseEntry.Version));

                this.Log().Info("Fixing up tray icons");

                var trayFixer = new TrayStateChanger();
                var appDir    = new DirectoryInfo(Utility.AppDirForRelease(rootAppDirectory, updateInfo.FutureReleaseEntry));
                var allExes   = appDir.GetFiles("*.exe").Select(x => x.Name).ToList();

                this.ErrorIfThrows(() => trayFixer.RemoveDeadEntries(allExes, rootAppDirectory, updateInfo.FutureReleaseEntry.Version.ToString()));
                progress(80);

                unshimOurselves();
                progress(85);

                try {
                    var currentVersion = updateInfo.CurrentlyInstalledVersion != null ?
                                         updateInfo.CurrentlyInstalledVersion.Version : null;

                    await cleanDeadVersions(currentVersion, newVersion);
                } catch (Exception ex) {
                    this.Log().WarnException("Failed to clean dead versions, continuing anyways", ex);
                }
                progress(100);

                return(ret);
            }
            public void CreateShortcutsForExecutable(string exeName, ShortcutLocation locations, bool updateOnly, string programArguments, string icon)
            {
                this.Log().Info("About to create shortcuts for {0}, rootAppDir {1}", exeName, rootAppDirectory);

                var releases    = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
                var thisRelease = Utility.FindCurrentVersion(releases);

                var zf = new ZipPackage(Path.Combine(
                                            Utility.PackageDirectoryForAppDir(rootAppDirectory),
                                            thisRelease.Filename));

                var exePath     = Path.Combine(Utility.AppDirForRelease(rootAppDirectory, thisRelease), exeName);
                var fileVerInfo = FileVersionInfo.GetVersionInfo(exePath);

                foreach (var f in (ShortcutLocation[])Enum.GetValues(typeof(ShortcutLocation)))
                {
                    if (!locations.HasFlag(f))
                    {
                        continue;
                    }

                    var file       = linkTargetForVersionInfo(f, zf, fileVerInfo);
                    var fileExists = File.Exists(file);

                    // NB: If we've already installed the app, but the shortcut
                    // is no longer there, we have to assume that the user didn't
                    // want it there and explicitly deleted it, so we shouldn't
                    // annoy them by recreating it.
                    if (!fileExists && updateOnly)
                    {
                        this.Log().Warn("Wanted to update shortcut {0} but it appears user deleted it", file);
                        continue;
                    }

                    this.Log().Info("Creating shortcut for {0} => {1}", exeName, file);

                    ShellLink sl;
                    this.ErrorIfThrows(() => Utility.Retry(() => {
                        File.Delete(file);

                        var target = Path.Combine(rootAppDirectory, exeName);
                        sl         = new ShellLink {
                            Target           = target,
                            IconPath         = icon ?? target,
                            IconIndex        = 0,
                            WorkingDirectory = Path.GetDirectoryName(exePath),
                            Description      = zf.Description,
                        };

                        if (!String.IsNullOrWhiteSpace(programArguments))
                        {
                            sl.Arguments += String.Format(" -a \"{0}\"", programArguments);
                        }

                        var appUserModelId      = String.Format("com.squirrel.{0}.{1}", zf.Id.Replace(" ", ""), exeName.Replace(".exe", "").Replace(" ", ""));
                        var toastActivatorCLSID = Utility.CreateGuidFromHash(appUserModelId).ToString();

                        sl.SetAppUserModelId(appUserModelId);
                        sl.SetToastActivatorCLSID(toastActivatorCLSID);

                        this.Log().Info("About to save shortcut: {0} (target {1}, workingDir {2}, args {3}, toastActivatorCSLID {4})", file, sl.Target, sl.WorkingDirectory, sl.Arguments, toastActivatorCLSID);
                        if (ModeDetector.InUnitTestRunner() == false)
                        {
                            sl.Save(file);
                        }
                    }, 4), "Can't write shortcut: " + file);
                }

                fixPinnedExecutables(zf.Version);
            }
Exemple #8
0
            public void CreateShortcutsForExecutable(string exeName, ShortcutLocation locations, bool updateOnly)
            {
                this.Log().Info("About to create shortcuts for {0}, rootAppDir {1}", exeName, rootAppDirectory);

                var releases    = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
                var thisRelease = Utility.FindCurrentVersion(releases);
                var updateExe   = Path.Combine(rootAppDirectory, "update.exe");

                var zf = new ZipPackage(Path.Combine(
                                            Utility.PackageDirectoryForAppDir(rootAppDirectory),
                                            thisRelease.Filename));

                var exePath     = Path.Combine(Utility.AppDirForRelease(rootAppDirectory, thisRelease), exeName);
                var fileVerInfo = FileVersionInfo.GetVersionInfo(exePath);

                foreach (var f in (ShortcutLocation[])Enum.GetValues(typeof(ShortcutLocation)))
                {
                    if (!locations.HasFlag(f))
                    {
                        continue;
                    }

                    var file       = linkTargetForVersionInfo(f, zf, fileVerInfo);
                    var fileExists = File.Exists(file);

                    // NB: If we've already installed the app, but the shortcut
                    // is no longer there, we have to assume that the user didn't
                    // want it there and explicitly deleted it, so we shouldn't
                    // annoy them by recreating it.
                    if (!fileExists && updateOnly)
                    {
                        this.Log().Warn("Wanted to update shortcut {0} but it appears user deleted it", file);
                        continue;
                    }

                    this.Log().Info("Creating shortcut for {0} => {1}", exeName, file);

                    ShellLink sl;
                    this.ErrorIfThrows(() => {
                        if (fileExists)
                        {
                            try {
                                sl = new ShellLink();

                                sl.Open(file);
                                if (sl.Target == updateExe && sl.Description == zf.Description && sl.IconPath == exePath)
                                {
                                    return;
                                }

                                File.Delete(file);
                            } catch (Exception ex) {
                                this.Log().WarnException("Tried to compare shortcut and failed", ex);
                                File.Delete(file);
                            }
                        }

                        sl = new ShellLink {
                            Target           = updateExe,
                            IconPath         = exePath,
                            IconIndex        = 0,
                            WorkingDirectory = Path.GetDirectoryName(exePath),
                            Description      = zf.Description,
                            Arguments        = "--processStart " + exeName,
                        };

                        sl.SetAppUserModelId(String.Format("com.squirrel.{0}.{1}", zf.Id, exeName.Replace(".exe", "")));

                        this.Log().Info("About to save shortcut: {0} (target {1}, workingDir {2}, args {3})", file, sl.Target, sl.WorkingDirectory, sl.Arguments);
                        if (ModeDetector.InUnitTestRunner() == false)
                        {
                            sl.Save(file);
                        }
                    }, "Can't write shortcut: " + file);
                }
            }
            public async Task <string> ApplyReleases(UpdateInfo updateInfo, bool silentInstall, bool attemptingFullInstall, Action <int> progress = null)
            {
                progress = progress ?? (_ => { });

                var release = await createFullPackagesFromDeltas(updateInfo.ReleasesToApply, updateInfo.CurrentlyInstalledVersion, x => progress(x * 4 / 5));

                // The numbers in these progress reports are rather arbitrary. Experience indicates that applying the deltas takes most of the time.
                // Allocating 80% to that process is a crude approximation. The remaining identifiable steps are simply allocated equal time chunks
                // of 4% each.
                // These changes should probably not be pushed upstream without further enhancement. The time to apply deltas is probably dependent
                // on the size and complexity of the package being updated.
                progress(80);

                if (release == null)
                {
                    if (attemptingFullInstall)
                    {
                        this.Log().Info("No release to install, running the app");
                        // JohnT: this doesn't work, because if the second argument ('isInitialInstall') is false, invokePostInstall does NOT
                        // run the app.  And we mustn't make it do so, or it will try to run the app after installing updates,
                        // since passing attemptingFullInstall for this argument in the other call below is what prevents running
                        // the app post-install when it is already running and updating itself.
                        // We could pass true here for isInitialInstall, but then the app will be invoked as if for the first time,
                        // but it clearly isn't the first time, because it was already installed.
                        // For our fork, it doesn't currently matter, because if we ARE running the full installer and there is
                        // nothing to do, we redo everything, which means that at this point in the code there IS something
                        // to install, namely, the current full release. So I'm just not trying to fix it for now.
                        // If we need to make this run the app we probably need distinct arguments for isInitialInstall and
                        // attemptingFullInstall (or 'runFullApp' or similar).
                        await invokePostInstall(updateInfo.CurrentlyInstalledVersion.Version, false, true, silentInstall);
                    }

                    progress(100);
                    return(getDirectoryForRelease(updateInfo.CurrentlyInstalledVersion.Version).FullName);
                }

                var ret = await this.ErrorIfThrows(() => installPackageToAppDir(updateInfo, release),
                                                   "Failed to install package to app dir");

                progress(84);

                var currentReleases = await this.ErrorIfThrows(() => updateLocalReleasesFile(),
                                                               "Failed to update local releases file");

                progress(88);

                var newVersion = currentReleases.MaxBy(x => x.Version).First().Version;

                executeSelfUpdate(newVersion);

                await this.ErrorIfThrows(() => invokePostInstall(newVersion, attemptingFullInstall, false, silentInstall),
                                         "Failed to invoke post-install");

                progress(92);

                this.Log().Info("Starting fixPinnedExecutables");
                this.ErrorIfThrows(() => fixPinnedExecutables(updateInfo.FutureReleaseEntry.Version));

                this.Log().Info("Fixing up tray icons");

                var trayFixer = new TrayStateChanger();
                var appDir    = new DirectoryInfo(Utility.AppDirForRelease(rootAppDirectory, updateInfo.FutureReleaseEntry));
                var allExes   = appDir.GetFiles("*.exe").Select(x => x.Name).ToList();

                this.ErrorIfThrows(() => trayFixer.RemoveDeadEntries(allExes, rootAppDirectory, updateInfo.FutureReleaseEntry.Version.ToString()));
                progress(96);

                unshimOurselves();
                progress(98);

                try {
                    var currentVersion = updateInfo.CurrentlyInstalledVersion != null ?
                                         updateInfo.CurrentlyInstalledVersion.Version : null;

                    await cleanDeadVersions(currentVersion, newVersion);
                } catch (Exception ex) {
                    this.Log().WarnException("Failed to clean dead versions, continuing anyways", ex);
                }
                progress(100);

                return(ret);
            }