diff --git a/src/Velopack/Windows/Shortcuts.cs b/src/Velopack/Windows/Shortcuts.cs index b2941c43..3b313070 100644 --- a/src/Velopack/Windows/Shortcuts.cs +++ b/src/Velopack/Windows/Shortcuts.cs @@ -51,11 +51,11 @@ namespace Velopack.Windows /// Log for diagnostic messages. protected ILogger Log { get; } - /// Locator to use for finding important application paths + /// Locator to use for finding important application paths. protected IVelopackLocator Locator { get; } /// - public Shortcuts(ILogger logger, IVelopackLocator locator) + public Shortcuts(ILogger logger = null, IVelopackLocator locator = null) { Log = logger; Locator = locator; @@ -70,7 +70,7 @@ namespace Velopack.Windows CreateShortcut( Locator.ThisExeRelativePath, location, - Environment.CommandLine.Contains("squirrel-install") == false, + false, null, // shortcut arguments null); // shortcut icon } @@ -96,7 +96,6 @@ namespace Velopack.Windows var pkgDir = Locator.PackagesDir; var currentDir = Locator.AppContentDir; var rootAppDirectory = Locator.RootAppDir; - Log.Info($"About to create shortcuts for {relativeExeName}, rootAppDir {rootAppDirectory}"); var pkgPath = Path.Combine(pkgDir, release.OriginalFilename); var zf = new ZipPackage(pkgPath); @@ -106,31 +105,11 @@ namespace Velopack.Windows var ret = new Dictionary(); foreach (var f in (ShortcutLocation[]) Enum.GetValues(typeof(ShortcutLocation))) { if (!locations.HasFlag(f)) continue; - - var file = LinkTargetForVersionInfo(f, zf, fileVerInfo, rootAppDirectory); - //var appUserModelId = Utility.GetAppUserModelId(zf.Id, exeName); - //var toastActivatorCLSDID = Utility.CreateGuidFromHash(appUserModelId).ToString(); - - Log.Info($"Creating shortcut for {relativeExeName} => {file}"); - //Log.Info($"appUserModelId: {appUserModelId} | toastActivatorCLSID: {toastActivatorCLSDID}"); - - var target = Path.Combine(rootAppDirectory, relativeExeName); - var sl = new ShellLink { - Target = target, - IconPath = target, - IconIndex = 0, - WorkingDirectory = Path.GetDirectoryName(exePath), - Description = zf.ProductDescription, - }; - - //if (!String.IsNullOrWhiteSpace(programArguments)) { - // sl.Arguments += String.Format(" -a \"{0}\"", programArguments); - //} - - //sl.SetAppUserModelId(appUserModelId); - //sl.SetToastActivatorCLSID(toastActivatorCLSDID); - - ret.Add(f, sl); + var file = LinkPathForVersionInfo(f, zf, fileVerInfo, rootAppDirectory); + if (File.Exists(file)) { + Log.Info($"Opening existing shortcut for {relativeExeName} ({file})"); + ret.Add(f, new ShellLink(file)); + } } return ret; @@ -160,7 +139,7 @@ namespace Velopack.Windows foreach (var f in (ShortcutLocation[]) Enum.GetValues(typeof(ShortcutLocation))) { if (!locations.HasFlag(f)) continue; - var file = LinkTargetForVersionInfo(f, zf, fileVerInfo, rootAppDirectory); + var file = LinkPathForVersionInfo(f, zf, fileVerInfo, rootAppDirectory); var fileExists = File.Exists(file); // NB: If we've already installed the app, but the shortcut @@ -222,7 +201,7 @@ namespace Velopack.Windows foreach (var f in (ShortcutLocation[]) Enum.GetValues(typeof(ShortcutLocation))) { if (!locations.HasFlag(f)) continue; - var file = LinkTargetForVersionInfo(f, zf, fileVerInfo, rootAppDirectory); + var file = LinkPathForVersionInfo(f, zf, fileVerInfo, rootAppDirectory); Log.Info($"Removing shortcut for {relativeExeName} => {file}"); try { if (File.Exists(file)) File.Delete(file); @@ -235,7 +214,7 @@ namespace Velopack.Windows /// /// Given an and return the target shortcut path. /// - protected virtual string LinkTargetForVersionInfo(ShortcutLocation location, IPackage package, FileVersionInfo versionInfo, string rootdir) + protected virtual string LinkPathForVersionInfo(ShortcutLocation location, IPackage package, FileVersionInfo versionInfo, string rootdir) { var possibleProductNames = new[] { versionInfo.ProductName, @@ -252,13 +231,13 @@ namespace Velopack.Windows var prodName = possibleCompanyNames.First(x => !String.IsNullOrWhiteSpace(x)); var pkgName = possibleProductNames.First(x => !String.IsNullOrWhiteSpace(x)); - return GetLinkTarget(location, pkgName, prodName, rootdir); + return GetLinkPath(location, pkgName, prodName, rootdir); } /// /// Given the application info, return the shortcut target path. /// - protected virtual string GetLinkTarget(ShortcutLocation location, string title, string applicationName, string rootdir, bool createDirectoryIfNecessary = true) + protected virtual string GetLinkPath(ShortcutLocation location, string title, string applicationName, string rootdir, bool createDirectoryIfNecessary = true) { var dir = default(string); diff --git a/test/PathHelper.cs b/test/PathHelper.cs index 47228efc..359640ac 100644 --- a/test/PathHelper.cs +++ b/test/PathHelper.cs @@ -32,6 +32,22 @@ public static class PathHelper public static string GetRustAsset(params string[] names) => Path.Combine(new string[] { GetRustBuildOutputDir() }.Concat(names).ToArray()); + public static string CopyRustAssetTo(string assetName, string dir) + { + var path = GetRustAsset(assetName); + var newPath = Path.Combine(dir, assetName); + File.Copy(path, newPath); + return newPath; + } + + public static string CopyFixtureTo(string fixtureName, string dir) + { + var path = GetFixture(fixtureName); + var newPath = Path.Combine(dir, fixtureName); + File.Copy(path, newPath); + return newPath; + } + public static string CopyUpdateTo(string dir) { var updateName = "update.exe"; diff --git a/test/Velopack.Tests/ShortcutTests.cs b/test/Velopack.Tests/ShortcutTests.cs new file mode 100644 index 00000000..de1d909c --- /dev/null +++ b/test/Velopack.Tests/ShortcutTests.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Velopack.Locators; +using Velopack.Windows; + +namespace Velopack.Tests +{ + public class ShortcutTests + { + private readonly ITestOutputHelper _output; + + public ShortcutTests(ITestOutputHelper output) + { + _output = output; + } + + [SkippableFact] + public void CanCreateAndRemoveShortcuts() + { + Skip.IfNot(VelopackRuntimeInfo.IsWindows); + using var logger = _output.BuildLoggerFor(); + string exeName = "NotSquirrelAwareApp.exe"; + + using var _1 = Utility.GetTempDirectory(out var pkgDir); + using var _2 = Utility.GetTempDirectory(out var appDir); + PathHelper.CopyFixtureTo("AvaloniaCrossPlat-1.0.15-win-full.nupkg", pkgDir); + PathHelper.CopyFixtureTo(exeName, appDir); + + var locator = new TestVelopackLocator("AvaloniaCrossPlat", "1.0.0", pkgDir, appDir, appDir, null, logger); + var sh = new Shortcuts(logger, locator); + var flag = ShortcutLocation.StartMenuRoot | ShortcutLocation.Desktop; + sh.DeleteShortcuts(exeName, flag); + sh.CreateShortcut(exeName, flag, false, ""); + var shortcuts = sh.FindShortcuts(exeName, flag); + Assert.Equal(2, shortcuts.Keys.Count); + + var startDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs"); + var desktopDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); + var lnkName = "SquirrelAwareApp.lnk"; + + var start = shortcuts[ShortcutLocation.StartMenuRoot]; + var desktop = shortcuts[ShortcutLocation.Desktop]; + + Assert.Equal(Path.Combine(startDir, lnkName), start.ShortCutFile); + Assert.Equal(Path.Combine(desktopDir, lnkName), desktop.ShortCutFile); + + sh.DeleteShortcuts(exeName, flag); + var after = sh.FindShortcuts(exeName, flag); + Assert.Equal(0, after.Keys.Count); + } + } +}