mirror of
				https://github.com/velopack/velopack.git
				synced 2025-10-25 15:19:22 +00:00 
			
		
		
		
	Re-implemented msi installer based on Clowd.Squirrel
This re-implements the msi installer that was present inside of Clowd.Squirrel. This is hidden behind some hidden options.
This commit is contained in:
		| @@ -20,6 +20,8 @@ namespace Velopack | ||||
|         Portable = 3, | ||||
|         /// <summary> An application installer archive. </summary> | ||||
|         Installer = 4, | ||||
|         /// <summary> A Windows Installer package (.msi) for the application.</summary> | ||||
|         Msi = 5, | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|   | ||||
| @@ -94,6 +94,10 @@ public class PackTask : MSBuildAsyncTask | ||||
|      | ||||
|     public string? Compression { get; set; } | ||||
| 
 | ||||
|     public bool BuildMsi { get; set; } | ||||
| 
 | ||||
|     public string? MsiVersionOverride { get; set; } | ||||
| 
 | ||||
|     protected override async Task<bool> ExecuteAsync(CancellationToken cancellationToken) | ||||
|     { | ||||
|         //System.Diagnostics.Debugger.Launch(); | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using Riok.Mapperly.Abstractions; | ||||
| using Velopack.Core; | ||||
| using Velopack.Packaging; | ||||
| using Velopack.Packaging.Unix.Commands; | ||||
| using Velopack.Packaging.Windows.Commands; | ||||
|   | ||||
| @@ -40,6 +40,16 @@ public static class DefaultName | ||||
|             throw new PlatformNotSupportedException("Platform not supported."); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public static string GetSuggestedMsiName(string id, string channel, RuntimeOs os) | ||||
|     { | ||||
|         var suffix = GetUniqueAssetSuffix(channel); | ||||
|         if (os == RuntimeOs.Windows) | ||||
|             return $"{id}{suffix}-DeploymentTool.msi"; | ||||
|         else | ||||
|             throw new PlatformNotSupportedException("Platform not supported."); | ||||
|     } | ||||
| 
 | ||||
|     private static string GetUniqueAssetSuffix(string channel) | ||||
|     { | ||||
|         return "-" + channel; | ||||
|   | ||||
| @@ -37,4 +37,5 @@ public class LinuxPackOptions : IPackOptions | ||||
|     public string Categories { get; set; } | ||||
|      | ||||
|     public string Compression { get; set; } | ||||
|     public bool BuildMsi => false; | ||||
| } | ||||
|   | ||||
| @@ -35,4 +35,5 @@ public class OsxPackOptions : OsxBundleOptions, IPackOptions | ||||
|     public string Channel { get; set; } | ||||
| 
 | ||||
|     public string Exclude { get; set; } | ||||
|     public bool BuildMsi => false; | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,10 @@ | ||||
| using System.Runtime.Versioning; | ||||
| using System.Globalization; | ||||
| using System.Runtime.Versioning; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Options; | ||||
| using NuGet.Versioning; | ||||
| using Velopack.Compression; | ||||
| using Velopack.Core; | ||||
| using Velopack.Core.Abstractions; | ||||
| @@ -25,7 +29,7 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions> | ||||
|             .Select(x => x.FullName) | ||||
|             .ToArray(); | ||||
| 
 | ||||
|         SignFilesImpl(Options, progress, filesToSign); | ||||
|         SignFilesImpl(progress, filesToSign); | ||||
| 
 | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
| @@ -198,7 +202,7 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions> | ||||
|         SetupBundle.CreatePackageBundle(targetSetupExe, releasePkg); | ||||
|         progress(50); | ||||
|         Log.Debug("Signing Setup bundle"); | ||||
|         SignFilesImpl(Options, CoreUtil.CreateProgressDelegate(progress, 50, 100), targetSetupExe); | ||||
|         SignFilesImpl(CoreUtil.CreateProgressDelegate(progress, 50, 100), targetSetupExe); | ||||
|         Log.Debug($"Setup bundle created '{Path.GetFileName(targetSetupExe)}'."); | ||||
|         progress(100); | ||||
| 
 | ||||
| @@ -237,6 +241,14 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions> | ||||
|         return dict; | ||||
|     } | ||||
| 
 | ||||
|     protected override Task CreateMsiPackage(Action<int> progress, string setupExePath, string msiPath) | ||||
|     { | ||||
|         if (VelopackRuntimeInfo.IsWindows) { | ||||
|             CompileWixTemplateToMsi(progress, setupExePath, msiPath); | ||||
|         } | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
| 
 | ||||
|     private void CreateExecutableStubForExe(string exeToCopy, string targetStubPath) | ||||
|     { | ||||
|         if (!File.Exists(exeToCopy)) { | ||||
| @@ -253,12 +265,12 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions> | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void SignFilesImpl(WindowsSigningOptions options, Action<int> progress, params string[] filePaths) | ||||
|     private void SignFilesImpl(Action<int> progress, params string[] filePaths) | ||||
|     { | ||||
|         var signParams = options.SignParameters; | ||||
|         var signTemplate = options.SignTemplate; | ||||
|         var signParallel = options.SignParallel; | ||||
|         var trustedSignMetadataPath = options.AzureTrustedSignFile; | ||||
|         var signParams = Options.SignParameters; | ||||
|         var signTemplate = Options.SignTemplate; | ||||
|         var signParallel = Options.SignParallel; | ||||
|         var trustedSignMetadataPath = Options.AzureTrustedSignFile; | ||||
|         var helper = new CodeSign(Log); | ||||
| 
 | ||||
|         if (string.IsNullOrEmpty(signParams) && string.IsNullOrEmpty(signTemplate) && string.IsNullOrEmpty(trustedSignMetadataPath)) { | ||||
| @@ -317,6 +329,83 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions> | ||||
|         // return dlibPath; | ||||
|     } | ||||
| 
 | ||||
|     [SupportedOSPlatform("windows")] | ||||
|     private void CompileWixTemplateToMsi(Action<int> progress, | ||||
|         string setupExePath, string msiFilePath) | ||||
|     { | ||||
|         bool packageAs64Bit =  | ||||
|             Options.TargetRuntime.Architecture is RuntimeCpu.x64 or RuntimeCpu.arm64; | ||||
| 
 | ||||
|         Log.Info($"Compiling machine-wide msi deployment tool in {(packageAs64Bit ? "64-bit" : "32-bit")} mode"); | ||||
| 
 | ||||
|         var outputDirectory = Path.GetDirectoryName(setupExePath); | ||||
|         var setupName = Path.GetFileNameWithoutExtension(setupExePath); | ||||
|         var culture = CultureInfo.GetCultureInfo("en-US").TextInfo.ANSICodePage; | ||||
| 
 | ||||
|         // WiX Identifiers may contain ASCII characters A-Z, a-z, digits, underscores (_), or | ||||
|         // periods(.). Every identifier must begin with either a letter or an underscore. | ||||
|         var wixId = Regex.Replace(Options.PackId, @"[^\w\.]", "_"); | ||||
|         if (char.GetUnicodeCategory(wixId[0]) == UnicodeCategory.DecimalDigitNumber) | ||||
|             wixId = "_" + wixId; | ||||
| 
 | ||||
|         Regex stacheRegex = new(@"\{\{(?<key>[^\}]+)\}\}", RegexOptions.Compiled); | ||||
| 
 | ||||
|         var wxsFile = Path.Combine(outputDirectory, wixId + ".wxs"); | ||||
|         var objFile = Path.Combine(outputDirectory, wixId + ".wixobj"); | ||||
| 
 | ||||
| 
 | ||||
|         var msiVersion = Options.MsiVersionOverride; | ||||
|         if (string.IsNullOrWhiteSpace(msiVersion)) { | ||||
|             var parsedVersion = SemanticVersion.Parse(Options.PackVersion); | ||||
|             msiVersion = $"{parsedVersion.Major}.{parsedVersion.Minor}.{parsedVersion.Patch}.0"; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             // apply dictionary to wsx template | ||||
|             var templateText = File.ReadAllText(HelperFile.WixTemplatePath); | ||||
| 
 | ||||
|             var templateResult = stacheRegex.Replace(templateText, match => { | ||||
|                 string key = match.Groups["key"].Value; | ||||
|                 return key switch { | ||||
|                     "Id" => wixId, | ||||
|                     "Title" => GetEffectiveTitle(), | ||||
|                     "Author" => GetEffectiveAuthors(), | ||||
|                     "Version" => msiVersion, | ||||
|                     "Summary" => GetEffectiveTitle(), | ||||
|                     "Codepage" => $"{culture}", | ||||
|                     "Platform" => packageAs64Bit ? "x64" : "x86", | ||||
|                     "ProgramFilesFolder" => packageAs64Bit ? "ProgramFiles64Folder" : "ProgramFilesFolder", | ||||
|                     "Win64YesNo" => packageAs64Bit ? "yes" : "no", | ||||
|                     "SetupName" => setupName, | ||||
|                     _ when key.StartsWith("IdAsGuid") => GuidUtil.CreateGuidFromHash($"{Options.PackId}:{key.Substring(8)}").ToString(), | ||||
|                     _ => match.Value, | ||||
|                 }; | ||||
|             }); | ||||
| 
 | ||||
|             File.WriteAllText(wxsFile, templateResult, Encoding.UTF8); | ||||
| 
 | ||||
|             // Candle reprocesses and compiles WiX source files into object files (.wixobj). | ||||
|             Log.Info("Compiling WiX Template (candle.exe)"); | ||||
|             var candleCommand = $"{HelperFile.WixCandlePath} -nologo -ext WixNetFxExtension -out \"{objFile}\" \"{wxsFile}\""; | ||||
|             _ = Exe.RunHostedCommand(candleCommand); | ||||
| 
 | ||||
|             progress(45); | ||||
| 
 | ||||
|             // Light links and binds one or more .wixobj files and creates a Windows Installer database (.msi or .msm).  | ||||
|             Log.Info("Linking WiX Template (light.exe)"); | ||||
|             var lightCommand = $"{HelperFile.WixLightPath} -ext WixNetFxExtension -spdb -sval -out \"{msiFilePath}\" \"{objFile}\""; | ||||
|             _ = Exe.RunHostedCommand(lightCommand); | ||||
| 
 | ||||
|             progress(90); | ||||
| 
 | ||||
|         } finally { | ||||
|             IoUtil.DeleteFileOrDirectoryHard(wxsFile, throwOnFailure: false); | ||||
|             IoUtil.DeleteFileOrDirectoryHard(objFile, throwOnFailure: false); | ||||
|         } | ||||
|         progress(100); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     protected override string[] GetMainExeSearchPaths(string packDirectory, string mainExeName) | ||||
|     { | ||||
|         return [ | ||||
|   | ||||
| @@ -23,4 +23,8 @@ public class WindowsPackOptions : WindowsReleasifyOptions, INugetPackCommand, IP | ||||
|     public bool NoInst { get; set; } | ||||
| 
 | ||||
|     public string Shortcuts { get; set; } | ||||
| 
 | ||||
|     public bool BuildMsi { get; set; } | ||||
| 
 | ||||
|     public string MsiVersionOverride { get; set; } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,4 @@ | ||||
| using Velopack.Core; | ||||
| 
 | ||||
| namespace Velopack.Packaging.Windows.Commands; | ||||
| namespace Velopack.Packaging.Windows.Commands; | ||||
| 
 | ||||
| public class WindowsReleasifyOptions : WindowsSigningOptions | ||||
| { | ||||
|   | ||||
| @@ -152,7 +152,7 @@ public class ResourceEdit | ||||
| 
 | ||||
|         var file = PEFile.FromBytes(File.ReadAllBytes(otherExeFile)); | ||||
|         var image = PEImage.FromFile(file); | ||||
|         _resources = image.Resources; | ||||
|         _resources = image.Resources ?? new ResourceDirectory((uint) 0); | ||||
|     } | ||||
| 
 | ||||
|     public void Commit() | ||||
|   | ||||
| @@ -9,4 +9,5 @@ public interface IPackOptions : INugetPackCommand, IPlatformOptions | ||||
|     string Exclude { get; set; } | ||||
|     bool NoPortable { get; set; } | ||||
|     bool NoInst { get; set; } | ||||
|     bool BuildMsi { get; } | ||||
| } | ||||
|   | ||||
| @@ -69,7 +69,7 @@ public static class Exe | ||||
|         var stdout = IoUtil.Retry(() => File.ReadAllText(outputFile).Trim(), 10, 1000); | ||||
|         var result = (process.ExitCode, stdout, "", command); | ||||
|         ProcessFailedException.ThrowIfNonZero(result); | ||||
|         return result.Item2; | ||||
|         return stdout; | ||||
|     } | ||||
| 
 | ||||
|     public static void RunHostedCommandNoWait(string command, string workDir = null) | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System.Runtime.Versioning; | ||||
| using System.Text; | ||||
| using Microsoft.Extensions.Logging; | ||||
| 
 | ||||
| #if !DEBUG | ||||
| @@ -70,6 +71,13 @@ public static class HelperFile | ||||
| 
 | ||||
|     public static string StubExecutablePath => FindHelperFile("stub.exe"); | ||||
| 
 | ||||
|     [SupportedOSPlatform("windows")] | ||||
|     public static string WixTemplatePath => FindHelperFile("wix\\template.wxs"); | ||||
|     [SupportedOSPlatform("windows")] | ||||
|     public static string WixCandlePath => FindHelperFile("wix\\candle.exe"); | ||||
|     [SupportedOSPlatform("windows")] | ||||
|     public static string WixLightPath => FindHelperFile("wix\\light.exe"); | ||||
| 
 | ||||
|     [SupportedOSPlatform("windows")] | ||||
|     public static string SignToolPath => FindHelperFile("signing\\signtool.exe"); | ||||
| 
 | ||||
| @@ -135,8 +143,14 @@ public static class HelperFile | ||||
|             files = files.Where(predicate); | ||||
| 
 | ||||
|         var result = files.FirstOrDefault(); | ||||
|         if (result == null && throwWhenNotFound) | ||||
|             throw new Exception($"HelperFile could not find '{toFind}'."); | ||||
|         if (result == null && throwWhenNotFound) { | ||||
|             StringBuilder msg = new(); | ||||
|             msg.AppendLine($"HelperFile could not find '{toFind}'."); | ||||
|             msg.AppendLine("Search paths:"); | ||||
|             foreach (var path in _searchPaths) | ||||
|                 msg.AppendLine($"  {Path.GetFullPath(path)}"); | ||||
|             throw new Exception(msg.ToString()); | ||||
|         } | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| using System.Collections.Concurrent; | ||||
| using System.Security; | ||||
| using System.Security; | ||||
| using System.Text.RegularExpressions; | ||||
| using Markdig; | ||||
| using Microsoft.Extensions.Logging; | ||||
| @@ -149,12 +148,13 @@ public abstract class PackageBuilder<T> : ICommand<T> | ||||
|                     }); | ||||
| 
 | ||||
|                 Task setupTask = null; | ||||
|                 string setupExePath = null; | ||||
|                 if (!Options.NoInst && TargetOs != RuntimeOs.Linux) { | ||||
|                     setupTask = ctx.RunTask( | ||||
|                         "Building setup package", | ||||
|                         async (progress) => { | ||||
|                             var suggestedName = DefaultName.GetSuggestedSetupName(packId, channel, TargetOs); | ||||
|                             var path = assetCache.MakeAssetPath(suggestedName, VelopackAssetType.Installer); | ||||
|                             var path = setupExePath = assetCache.MakeAssetPath(suggestedName, VelopackAssetType.Installer); | ||||
|                             await CreateSetupPackage(progress, releasePath, packDirectory, path); | ||||
|                         }); | ||||
|                 } | ||||
| @@ -177,6 +177,16 @@ public abstract class PackageBuilder<T> : ICommand<T> | ||||
|                 if (TargetOs != RuntimeOs.Linux && portableTask != null) await portableTask; | ||||
|                 if (setupTask != null) await setupTask; | ||||
| 
 | ||||
|                 if (!Options.NoInst && Options.BuildMsi && TargetOs == RuntimeOs.Windows) { | ||||
|                     await ctx.RunTask( | ||||
|                         "Building MSI package", | ||||
|                         async (progress) => { | ||||
|                             var msiName = DefaultName.GetSuggestedMsiName(packId, channel, TargetOs); | ||||
|                             var msiPath = assetCache.MakeAssetPath(msiName, VelopackAssetType.Msi); | ||||
|                             await CreateMsiPackage(progress, setupExePath, msiPath); | ||||
|                         }); | ||||
|                 } | ||||
| 
 | ||||
|                 await ctx.RunTask( | ||||
|                     "Post-process steps", | ||||
|                     (progress) => { | ||||
| @@ -196,8 +206,8 @@ public abstract class PackageBuilder<T> : ICommand<T> | ||||
|     protected virtual string GenerateNuspecContent() | ||||
|     { | ||||
|         var packId = Options.PackId; | ||||
|         var packTitle = Options.PackTitle ?? Options.PackId; | ||||
|         var packAuthors = Options.PackAuthors ?? Options.PackId; | ||||
|         var packTitle = GetEffectiveTitle(); | ||||
|         var packAuthors = GetEffectiveAuthors(); | ||||
|         var packVersion = Options.PackVersion; | ||||
|         var releaseNotes = Options.ReleaseNotes; | ||||
|         var rid = Options.TargetRuntime; | ||||
| @@ -240,8 +250,8 @@ public abstract class PackageBuilder<T> : ICommand<T> | ||||
|             <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> | ||||
|             <metadata> | ||||
|             <id>{packId}</id> | ||||
|             <title>{packTitle ?? packId}</title> | ||||
|             <description>{packTitle ?? packId}</description> | ||||
|             <title>{packTitle}</title> | ||||
|             <description>{packTitle}</description> | ||||
|             <authors>{packAuthors ?? packId}</authors> | ||||
|             <version>{packVersion}</version> | ||||
|             <channel>{Options.Channel}</channel> | ||||
| @@ -277,6 +287,11 @@ public abstract class PackageBuilder<T> : ICommand<T> | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
| 
 | ||||
|     protected virtual Task CreateMsiPackage(Action<int> progress, string setupExePath, string msiPath) | ||||
|     { | ||||
|         return Task.CompletedTask; | ||||
|     } | ||||
| 
 | ||||
|     protected virtual async Task CreateReleasePackage(Action<int> progress, string packDir, string outputPath) | ||||
|     { | ||||
|         var stagingDir = TempDir.CreateSubdirectory("CreateReleasePackage"); | ||||
| @@ -395,4 +410,8 @@ public abstract class PackageBuilder<T> : ICommand<T> | ||||
|             """;
 | ||||
|         File.WriteAllText(Path.Combine(relsDir, ".rels"), rels); | ||||
|     } | ||||
| 
 | ||||
|     protected string GetEffectiveTitle() => Options.PackTitle ?? Options.PackId; | ||||
| 
 | ||||
|     protected string GetEffectiveAuthors() => Options.PackAuthors ?? Options.PackId; | ||||
| } | ||||
| @@ -20,6 +20,10 @@ public class WindowsPackCommand : PackCommand | ||||
| 
 | ||||
|     public string Shortcuts { get; private set; } | ||||
| 
 | ||||
|     public bool BuildMsi { get; private set; } | ||||
| 
 | ||||
|     public string MsiVersionOverride { get; private set; } | ||||
| 
 | ||||
|     public WindowsPackCommand() | ||||
|         : base("pack", "Creates a release from a folder containing application files.", RuntimeOs.Windows) | ||||
|     { | ||||
| @@ -69,6 +73,17 @@ public class WindowsPackCommand : PackCommand | ||||
|                 .SetArgumentHelpName("PATH"); | ||||
| 
 | ||||
|             this.AreMutuallyExclusive(signTemplate, signParams, azTrustedSign); | ||||
| 
 | ||||
|             AddOption<bool>((v) => BuildMsi = v, "--msi") | ||||
|                 .SetDescription("Compile a .msi machine-wide deployment tool.") | ||||
|                 .SetHidden() | ||||
|                 .SetArgumentHelpName("BITNESS"); | ||||
| 
 | ||||
|             AddOption<string>((v) => MsiVersionOverride = v, "--msiVersion") | ||||
|                 .SetDescription("Override the product version for the generated msi.") | ||||
|                 .SetArgumentHelpName("VERSION") | ||||
|                 .SetHidden() | ||||
|                 .MustBeValidMsiVersion(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -15,4 +15,10 @@ | ||||
|     <PackageReference Include="System.Formats.Asn1" Version="9.0.1" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <Reference Include="Microsoft.Deployment.WindowsInstaller"> | ||||
|       <HintPath>..\..\vendor\wix\Microsoft.Deployment.WindowsInstaller.dll</HintPath> | ||||
|     </Reference> | ||||
|   </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
|   | ||||
| @@ -2,17 +2,18 @@ | ||||
| using System.Globalization; | ||||
| using System.Runtime.Versioning; | ||||
| using System.Xml.Linq; | ||||
| using Microsoft.Deployment.WindowsInstaller; | ||||
| using Microsoft.Win32; | ||||
| using NuGet.Packaging; | ||||
| using Velopack.Compression; | ||||
| using Velopack.Core; | ||||
| using Velopack.Packaging.Commands; | ||||
| using Velopack.Packaging.Exceptions; | ||||
| using Velopack.Packaging.Windows.Commands; | ||||
| using Velopack.Util; | ||||
| using Velopack.Vpk; | ||||
| using Velopack.Vpk.Logging; | ||||
| using Velopack.Windows; | ||||
| using static Azure.Core.HttpHeader; | ||||
| 
 | ||||
| namespace Velopack.Packaging.Tests; | ||||
| 
 | ||||
| @@ -26,7 +27,7 @@ public class WindowsPackTests | ||||
|         _output = output; | ||||
|     } | ||||
| 
 | ||||
|     private WindowsPackCommandRunner GetPackRunner(ILogger logger) | ||||
|     private static WindowsPackCommandRunner GetPackRunner(ILogger logger) | ||||
|     { | ||||
|         var console = new BasicConsole(logger, new VelopackDefaults(false)); | ||||
|         return new WindowsPackCommandRunner(logger, console); | ||||
| @@ -199,6 +200,7 @@ public class WindowsPackTests | ||||
|             TargetRuntime = RID.Parse("win-x64"), | ||||
|             PackDirectory = tmpOutput, | ||||
|             Shortcuts = "Desktop,StartMenuRoot", | ||||
|             NoPortable = true | ||||
|         }; | ||||
| 
 | ||||
|         var runner = GetPackRunner(logger); | ||||
| @@ -207,7 +209,7 @@ public class WindowsPackTests | ||||
|         var setupPath1 = Path.Combine(tmpReleaseDir, $"{id}-win-Setup.exe"); | ||||
|         Assert.True(File.Exists(setupPath1)); | ||||
| 
 | ||||
|         RunNoCoverage(setupPath1, new[] { "--silent", "--installto", tmpInstallDir }, Environment.CurrentDirectory, logger); | ||||
|         RunNoCoverage(setupPath1, ["--silent", "--installto", tmpInstallDir], Environment.CurrentDirectory, logger); | ||||
| 
 | ||||
|         var updatePath = Path.Combine(tmpInstallDir, "Update.exe"); | ||||
|         Assert.True(File.Exists(updatePath)); | ||||
| @@ -244,18 +246,17 @@ public class WindowsPackTests | ||||
|         var date = DateTime.Now.ToString("yyyyMMdd", CultureInfo.InvariantCulture); | ||||
|         Assert.Equal(date, installDate.Trim('\0')); | ||||
| 
 | ||||
|         var uninstOutput = RunNoCoverage(updatePath, new string[] { "--silent", "--uninstall" }, Environment.CurrentDirectory, logger); | ||||
|         var uninstOutput = RunNoCoverage(updatePath, ["--silent", "--uninstall"], Environment.CurrentDirectory, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "Y", uninstOutput); // this checks that the self-delete succeeded | ||||
| 
 | ||||
|         Assert.False(File.Exists(startLnk)); | ||||
|         Assert.False(File.Exists(desktopLnk)); | ||||
|         Assert.False(File.Exists(appPath)); | ||||
| 
 | ||||
|         using (var key2 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default) | ||||
|                    .OpenSubKey(uninstallRegSubKey + "\\" + id, RegistryKeyPermissionCheck.ReadSubTree)) { | ||||
|         using var key2 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default) | ||||
|                    .OpenSubKey(uninstallRegSubKey + "\\" + id, RegistryKeyPermissionCheck.ReadSubTree); | ||||
|         Assert.Null(key2); | ||||
|     } | ||||
|     } | ||||
| 
 | ||||
|     [SkippableFact] | ||||
|     public void TestAppAutoUpdatesWhenLocalIsAvailable() | ||||
| @@ -274,7 +275,7 @@ public class WindowsPackTests | ||||
|         var setupPath1 = Path.Combine(releaseDir, $"{id}-win-Setup.exe"); | ||||
|         RunNoCoverage( | ||||
|             setupPath1, | ||||
|             new string[] { "--silent", "--installto", installDir }, | ||||
|             ["--silent", "--installto", installDir], | ||||
|             Environment.GetFolderPath(Environment.SpecialFolder.Desktop), | ||||
|             logger); | ||||
| 
 | ||||
| @@ -287,19 +288,19 @@ public class WindowsPackTests | ||||
|         var mvTo = Path.Combine(installDir, "packages", fileName); | ||||
|         File.Copy(mvFrom, mvTo); | ||||
| 
 | ||||
|         RunCoveredDotnet(appPath, new string[] { "--autoupdate" }, installDir, logger, exitCode: null); | ||||
|         RunCoveredDotnet(appPath, ["--autoupdate"], installDir, logger, exitCode: null); | ||||
| 
 | ||||
|         Thread.Sleep(3000); // update.exe runs in separate process | ||||
| 
 | ||||
|         var chk1version = RunCoveredDotnet(appPath, new string[] { "version" }, installDir, logger); | ||||
|         var chk1version = RunCoveredDotnet(appPath, ["version"], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "2.0.0", chk1version); | ||||
|     } | ||||
| 
 | ||||
|     [SkippableFact] | ||||
|     public void TestPackGeneratesValidDelta() | ||||
|     { | ||||
|         using var _1 = TempUtil.GetTempDirectory(out var releaseDir); | ||||
|         Skip.IfNot(VelopackRuntimeInfo.IsWindows); | ||||
|         using var _1 = TempUtil.GetTempDirectory(out var releaseDir); | ||||
|         using var logger = _output.BuildLoggerFor<WindowsPackTests>(); | ||||
|         string id = "SquirrelDeltaTest"; | ||||
|         PackTestApp(id, "1.0.0", "version 1 test", releaseDir, logger); | ||||
| @@ -338,7 +339,7 @@ public class WindowsPackTests | ||||
|             new DeltaPatchOptions { | ||||
|                 BasePackage = Path.Combine(releaseDir, $"{id}-1.0.0-full.nupkg"), | ||||
|                 OutputFile = output, | ||||
|                 PatchFiles = new[] { new FileInfo(deltaPath) }, | ||||
|                 PatchFiles = [new FileInfo(deltaPath)], | ||||
|             }).GetAwaiterResult(); | ||||
| 
 | ||||
|         // are the packages the same? | ||||
| @@ -437,7 +438,7 @@ public class WindowsPackTests | ||||
|         var setupPath1 = Path.Combine(releaseDir, $"{id}-win-Setup.exe"); | ||||
|         RunNoCoverage( | ||||
|             setupPath1, | ||||
|             new string[] { "--silent", "--installto", installDir }, | ||||
|             ["--silent", "--installto", installDir], | ||||
|             Environment.GetFolderPath(Environment.SpecialFolder.Desktop), | ||||
|             logger); | ||||
| 
 | ||||
| @@ -451,11 +452,11 @@ public class WindowsPackTests | ||||
|         logger.Info("TEST: v1 installed"); | ||||
| 
 | ||||
|         // check app output | ||||
|         var chk1test = RunCoveredDotnet(appPath, new string[] { "test" }, installDir, logger); | ||||
|         var chk1test = RunCoveredDotnet(appPath, ["test"], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "version 1 test", chk1test); | ||||
|         var chk1version = RunCoveredDotnet(appPath, new string[] { "version" }, installDir, logger); | ||||
|         var chk1version = RunCoveredDotnet(appPath, ["version"], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "1.0.0", chk1version); | ||||
|         var chk1check = RunCoveredDotnet(appPath, new string[] { "check", releaseDir }, installDir, logger); | ||||
|         var chk1check = RunCoveredDotnet(appPath, ["check", releaseDir], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "no updates", chk1check); | ||||
|         logger.Info("TEST: v1 output verified"); | ||||
| 
 | ||||
| @@ -463,7 +464,7 @@ public class WindowsPackTests | ||||
|         PackTestApp(id, "2.0.0", "version 2 test", releaseDir, logger); | ||||
| 
 | ||||
|         // check can find v2 update | ||||
|         var chk2check = RunCoveredDotnet(appPath, new string[] { "check", releaseDir }, installDir, logger); | ||||
|         var chk2check = RunCoveredDotnet(appPath, ["check", releaseDir], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "update: 2.0.0", chk2check); | ||||
|         logger.Info("TEST: found v2 update"); | ||||
| 
 | ||||
| @@ -476,17 +477,17 @@ public class WindowsPackTests | ||||
| 
 | ||||
|         // perform full update, check that we get v3 | ||||
|         // apply should fail if there's not an update downloaded | ||||
|         RunCoveredDotnet(appPath, new string[] { "apply", releaseDir }, installDir, logger, exitCode: -1); | ||||
|         RunCoveredDotnet(appPath, new string[] { "download", releaseDir }, installDir, logger); | ||||
|         RunCoveredDotnet(appPath, new string[] { "apply", releaseDir }, installDir, logger, exitCode: null); | ||||
|         RunCoveredDotnet(appPath, ["apply", releaseDir], installDir, logger, exitCode: -1); | ||||
|         RunCoveredDotnet(appPath, ["download", releaseDir], installDir, logger); | ||||
|         RunCoveredDotnet(appPath, ["apply", releaseDir], installDir, logger, exitCode: null); | ||||
|         logger.Info("TEST: v3 applied"); | ||||
| 
 | ||||
|         // check app output | ||||
|         var chk3test = RunCoveredDotnet(appPath, new string[] { "test" }, installDir, logger); | ||||
|         var chk3test = RunCoveredDotnet(appPath, ["test"], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "version 3 test", chk3test); | ||||
|         var chk3version = RunCoveredDotnet(appPath, new string[] { "version" }, installDir, logger); | ||||
|         var chk3version = RunCoveredDotnet(appPath, ["version"], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "3.0.0", chk3version); | ||||
|         var ch3check2 = RunCoveredDotnet(appPath, new string[] { "check", releaseDir }, installDir, logger); | ||||
|         var ch3check2 = RunCoveredDotnet(appPath, ["check", releaseDir], installDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "no updates", ch3check2); | ||||
|         logger.Info("TEST: v3 output verified"); | ||||
| 
 | ||||
| @@ -504,7 +505,7 @@ public class WindowsPackTests | ||||
| 
 | ||||
|         // uninstall | ||||
|         var updatePath = Path.Combine(installDir, "Update.exe"); | ||||
|         RunNoCoverage(updatePath, new string[] { "--silent", "--uninstall" }, Environment.CurrentDirectory, logger); | ||||
|         RunNoCoverage(updatePath, ["--silent", "--uninstall"], Environment.CurrentDirectory, logger); | ||||
|         logger.Info("TEST: uninstalled / complete"); | ||||
|     } | ||||
| 
 | ||||
| @@ -543,8 +544,8 @@ public class WindowsPackTests | ||||
|         using var _1 = TempUtil.GetTempDirectory(out var releaseDir); | ||||
|         PackTestApp("LegacyTestApp", "2.0.0", "hello!", releaseDir, logger); | ||||
| 
 | ||||
|         RunNoCoverage(appExe, new string[] { "download", releaseDir }, currentDir, logger, exitCode: 0); | ||||
|         RunNoCoverage(appExe, new string[] { "apply", releaseDir }, currentDir, logger, exitCode: null); | ||||
|         RunNoCoverage(appExe, ["download", releaseDir], currentDir, logger, exitCode: 0); | ||||
|         RunNoCoverage(appExe, ["apply", releaseDir], currentDir, logger, exitCode: null); | ||||
| 
 | ||||
|         logger.Info("TEST: " + DateTime.Now.ToLongTimeString()); | ||||
| 
 | ||||
| @@ -555,7 +556,7 @@ public class WindowsPackTests | ||||
|         logger.Info("TEST: " + DateTime.Now.ToLongTimeString()); | ||||
| 
 | ||||
|         if (origDirName != "current") { | ||||
|             Assert.True(!Directory.Exists(currentDir)); | ||||
|             Assert.False(Directory.Exists(currentDir)); | ||||
|             currentDir = Path.Combine(rootDir, "current"); | ||||
|         } | ||||
| 
 | ||||
| @@ -569,10 +570,90 @@ public class WindowsPackTests | ||||
|         // this is the file written by TestApp when it's detected the squirrel restart. if this is here, everything went smoothly. | ||||
|         Assert.True(File.Exists(Path.Combine(rootDir, "restarted"))); | ||||
| 
 | ||||
|         var chk3version = RunNoCoverage(appExe, new string[] { "version" }, currentDir, logger); | ||||
|         var chk3version = RunNoCoverage(appExe, ["version"], currentDir, logger); | ||||
|         Assert.EndsWith(Environment.NewLine + "2.0.0", chk3version); | ||||
|     } | ||||
| 
 | ||||
|     [SkippableFact] | ||||
|     public async Task TestPackGeneratesMsi() | ||||
|     { | ||||
|         Skip.IfNot(VelopackRuntimeInfo.IsWindows); | ||||
| 
 | ||||
|         using var logger = _output.BuildLoggerFor<WindowsPackTests>(); | ||||
| 
 | ||||
|         using var _1 = TempUtil.GetTempDirectory(out var tmpOutput); | ||||
|         using var _2 = TempUtil.GetTempDirectory(out var tmpReleaseDir); | ||||
| 
 | ||||
|         var exe = "testapp.exe"; | ||||
|         var pdb = Path.ChangeExtension(exe, ".pdb"); | ||||
|         var id = "Test.Squirrel-App"; | ||||
|         var version = "1.2.3"; | ||||
| 
 | ||||
|         PathHelper.CopyRustAssetTo(exe, tmpOutput); | ||||
|         PathHelper.CopyRustAssetTo(pdb, tmpOutput); | ||||
| 
 | ||||
|         var options = new WindowsPackOptions { | ||||
|             EntryExecutableName = exe, | ||||
|             ReleaseDir = new DirectoryInfo(tmpReleaseDir), | ||||
|             PackId = id, | ||||
|             PackVersion = version, | ||||
|             TargetRuntime = RID.Parse("win-x64"), | ||||
|             PackDirectory = tmpOutput, | ||||
|             Shortcuts = "Desktop,StartMenuRoot", | ||||
|             BuildMsi = true | ||||
|         }; | ||||
| 
 | ||||
|         var runner = GetPackRunner(logger); | ||||
|         await runner.Run(options); | ||||
| 
 | ||||
|         string msiPath = Path.Combine(tmpReleaseDir, $"{id}-win-DeploymentTool.msi"); | ||||
|         Assert.True(File.Exists(msiPath)); | ||||
|         using Database db = new Database(msiPath); | ||||
|         var msiVersion = db.ExecuteScalar("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'") as string; | ||||
|         Assert.Equal("1.2.3.0", msiVersion); | ||||
|     } | ||||
| 
 | ||||
|     [SkippableFact] | ||||
|     public async Task TestPackGeneratesMsiWithSpecifiedVersion() | ||||
|     { | ||||
|         Skip.IfNot(VelopackRuntimeInfo.IsWindows); | ||||
| 
 | ||||
|         using var logger = _output.BuildLoggerFor<WindowsPackTests>(); | ||||
| 
 | ||||
|         using var _1 = TempUtil.GetTempDirectory(out var tmpOutput); | ||||
|         using var _2 = TempUtil.GetTempDirectory(out var tmpReleaseDir); | ||||
| 
 | ||||
|         var exe = "testapp.exe"; | ||||
|         var pdb = Path.ChangeExtension(exe, ".pdb"); | ||||
|         var id = "Test.Squirrel-App"; | ||||
|         var version = "1.0.0"; | ||||
| 
 | ||||
|         PathHelper.CopyRustAssetTo(exe, tmpOutput); | ||||
|         PathHelper.CopyRustAssetTo(pdb, tmpOutput); | ||||
| 
 | ||||
|         var options = new WindowsPackOptions { | ||||
|             EntryExecutableName = exe, | ||||
|             ReleaseDir = new DirectoryInfo(tmpReleaseDir), | ||||
|             PackId = id, | ||||
|             PackVersion = version, | ||||
|             TargetRuntime = RID.Parse("win-x64"), | ||||
|             PackDirectory = tmpOutput, | ||||
|             Shortcuts = "Desktop,StartMenuRoot", | ||||
|             BuildMsi = true, | ||||
|             MsiVersionOverride = "4.5.6.1" | ||||
|         }; | ||||
| 
 | ||||
|         var runner = GetPackRunner(logger); | ||||
|         await runner.Run(options); | ||||
| 
 | ||||
|         string msiPath = Path.Combine(tmpReleaseDir, $"{id}-win-DeploymentTool.msi"); | ||||
|         Assert.True(File.Exists(msiPath)); | ||||
| 
 | ||||
|         using Database db = new Database(msiPath); | ||||
|         var msiVersion = db.ExecuteScalar("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'") as string; | ||||
|         Assert.Equal("4.5.6.1", msiVersion); | ||||
|     } | ||||
| 
 | ||||
|     private static string ReadFileWithRetry(string path, ILogger logger) | ||||
|     { | ||||
|         return IoUtil.Retry( | ||||
| @@ -610,7 +691,7 @@ public class WindowsPackTests | ||||
|     //    return RunImpl(psi, logger, exitCode); | ||||
|     //} | ||||
| 
 | ||||
|     private string RunImpl(ProcessStartInfo psi, ILogger logger, int? exitCode = 0) | ||||
|     private static string RunImpl(ProcessStartInfo psi, ILogger logger, int? exitCode = 0) | ||||
|     { | ||||
|         //logger.Info($"TEST: Running {psi.FileName} {psi.ArgumentList.Aggregate((a, b) => $"{a} {b}")}"); | ||||
|         //using var p = Process.Start(psi); | ||||
| @@ -679,7 +760,7 @@ public class WindowsPackTests | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private string RunCoveredDotnet(string exe, string[] args, string workingDir, ILogger logger, int? exitCode = 0) | ||||
|     private static string RunCoveredDotnet(string exe, string[] args, string workingDir, ILogger logger, int? exitCode = 0) | ||||
|     { | ||||
|         var outputfile = PathHelper.GetTestRootPath($"coverage.rundotnet.{RandomString(8)}.xml"); | ||||
| 
 | ||||
| @@ -703,7 +784,7 @@ public class WindowsPackTests | ||||
|         return RunImpl(psi, logger, exitCode); | ||||
|     } | ||||
| 
 | ||||
|     private static Random _random = new Random(); | ||||
|     private static readonly Random _random = Random.Shared; | ||||
| 
 | ||||
|     private static string RandomString(int length) | ||||
|     { | ||||
| @@ -727,7 +808,7 @@ public class WindowsPackTests | ||||
|         return RunImpl(psi, logger, exitCode); | ||||
|     } | ||||
| 
 | ||||
|     private void PackTestApp(string id, string version, string testString, string releaseDir, ILogger logger, bool addNewFile = false) | ||||
|     private static void PackTestApp(string id, string version, string testString, string releaseDir, ILogger logger, bool addNewFile = false) | ||||
|     { | ||||
|         var projDir = PathHelper.GetTestRootPath("TestApp"); | ||||
|         var testStringFile = Path.Combine(projDir, "Const.cs"); | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/Microsoft.Deployment.Resources.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/Microsoft.Deployment.Resources.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/Microsoft.Deployment.WindowsInstaller.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/Microsoft.Deployment.WindowsInstaller.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/WixNetFxExtension.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/WixNetFxExtension.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/candle.exe
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/candle.exe
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										18
									
								
								vendor/wix/candle.exe.config
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/wix/candle.exe.config
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <?xml version="1.0" encoding="utf-8" ?> | ||||
| <!-- | ||||
|   <copyright file="app.config" company="Outercurve Foundation"> | ||||
|     Copyright (c) 2004, Outercurve Foundation. | ||||
|     This software is released under Microsoft Reciprocal License (MS-RL). | ||||
|     The license and further copyright text can be found in the file | ||||
|     LICENSE.TXT at the root directory of the distribution. | ||||
|   </copyright> | ||||
| --> | ||||
| <configuration> | ||||
|     <startup useLegacyV2RuntimeActivationPolicy="true"> | ||||
|         <supportedRuntime version="v4.0" /> | ||||
|         <supportedRuntime version="v2.0.50727" /> | ||||
|     </startup> | ||||
|     <runtime> | ||||
|         <loadFromRemoteSources enabled="true"/> | ||||
|     </runtime> | ||||
| </configuration> | ||||
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/darice.cub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/darice.cub
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/light.exe
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/light.exe
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										18
									
								
								vendor/wix/light.exe.config
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/wix/light.exe.config
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <?xml version="1.0" encoding="utf-8" ?> | ||||
| <!-- | ||||
|   <copyright file="app.config" company="Outercurve Foundation"> | ||||
|     Copyright (c) 2004, Outercurve Foundation. | ||||
|     This software is released under Microsoft Reciprocal License (MS-RL). | ||||
|     The license and further copyright text can be found in the file | ||||
|     LICENSE.TXT at the root directory of the distribution. | ||||
|   </copyright> | ||||
| --> | ||||
| <configuration> | ||||
|     <startup useLegacyV2RuntimeActivationPolicy="true"> | ||||
|         <supportedRuntime version="v4.0" /> | ||||
|         <supportedRuntime version="v2.0.50727" /> | ||||
|     </startup> | ||||
|     <runtime> | ||||
|         <loadFromRemoteSources enabled="true"/> | ||||
|     </runtime> | ||||
| </configuration> | ||||
							
								
								
									
										39
									
								
								vendor/wix/template.wxs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/wix/template.wxs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"> | ||||
|   <Product Id="*" Name="{{Title}} Deployment Tool" Language="1033" Codepage="{{Codepage}}" Version="{{Version}}" UpgradeCode="{{IdAsGuid1}}" Manufacturer="{{Author}}"> | ||||
|  | ||||
|     <Package Description="This package installs a deployment tool for {{Title}}. Not {{Title}} itself. {{Title}} is only installed if a user logs into the machine." InstallScope="perMachine" Comments="Comments" InstallerVersion="200" Compressed="yes" Platform="{{Platform}}"/> | ||||
|     <MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A later version of this product is already installed. Setup will now exit."/> | ||||
|     <Media Id="1" Cabinet="contents.cab" EmbedCab="yes" CompressionLevel="high"/> | ||||
|  | ||||
|     <PropertyRef Id="NETFRAMEWORK45" /> | ||||
|  | ||||
|     <Condition Message="This application requires .NET Framework 4.5 or higher. Please install the latest .NET Framework then run this installer again."> | ||||
|       <![CDATA[Installed OR NETFRAMEWORK45]]> | ||||
|     </Condition> | ||||
|  | ||||
|     <Directory Id="TARGETDIR" Name="SourceDir"> | ||||
|       <Directory Id="{{ProgramFilesFolder}}"> | ||||
|         <Directory Id="APPLICATIONROOTDIRECTORY" Name="{{Title}} Deployment Tool" /> | ||||
|       </Directory> | ||||
|     </Directory> | ||||
|  | ||||
|     <DirectoryRef Id="APPLICATIONROOTDIRECTORY"> | ||||
|       <Component Id="{{Id}}.exe" Guid="{{IdAsGuid2}}" Win64="{{Win64YesNo}}"> | ||||
|         <File Id="{{Id}}.exe" Name="{{Id}}DeploymentTool.exe" Source="./{{SetupName}}.exe" KeyPath="yes"/> | ||||
|       </Component> | ||||
|     </DirectoryRef> | ||||
|  | ||||
|     <DirectoryRef Id="TARGETDIR"> | ||||
|       <Component Id="RegistryEntries" Guid="{{IdAsGuid3}}" Win64="{{Win64YesNo}}"> | ||||
|         <RegistryKey Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Run"> | ||||
|           <RegistryValue Type="expandable" Name="{{Id}}Deployment" Value=""[#{{Id}}.exe]" --checkInstall" /> | ||||
|         </RegistryKey> | ||||
|       </Component> | ||||
|     </DirectoryRef> | ||||
|  | ||||
|     <Feature Id="MainApplication" Title="Main Application" Level="1"> | ||||
|       <ComponentRef Id="{{Id}}.exe" /> | ||||
|       <ComponentRef Id="RegistryEntries" /> | ||||
|     </Feature> | ||||
|   </Product> | ||||
| </Wix> | ||||
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/wconsole.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/wconsole.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/winterop.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/winterop.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								vendor/wix/wix.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/wix/wix.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user