diff --git a/build.ps1 b/build.ps1 index 44353849..5e4d9681 100644 --- a/build.ps1 +++ b/build.ps1 @@ -38,7 +38,6 @@ Copy-Item "$In\Win32\Setup.exe" -Destination "$BinOut" Copy-Item "$In\Win32\StubExecutable.exe" -Destination "$BinOut" Copy-Item "$PSScriptRoot\vendor\rcedit.exe" -Destination "$BinOut" Copy-Item "$PSScriptRoot\vendor\signtool.exe" -Destination "$BinOut" -Copy-Item "$PSScriptRoot\vendor\singlefilehost.exe" -Destination "$BinOut" Copy-Item -Path "$PSScriptRoot\vendor\7za.exe" -Destination "$BinOut" # Clean up files we do not need to create a nuget package diff --git a/src/Squirrel.CommandLine.Windows/DotnetUtil.cs b/src/Squirrel.CommandLine.Windows/DotnetUtil.cs index 28bc0161..d1a5de52 100644 --- a/src/Squirrel.CommandLine.Windows/DotnetUtil.cs +++ b/src/Squirrel.CommandLine.Windows/DotnetUtil.cs @@ -119,26 +119,20 @@ namespace Squirrel.CommandLine { using var _ = Utility.GetTempDirectory(out var tmpdir); var sourceName = Path.GetFileNameWithoutExtension(sourceFile); + var newAppHost = Path.Combine(tmpdir, sourceName + ".exe"); - // extract Update.exe to tmp dir - Log.Info("Extracting Update.exe resources to temp directory"); + // extract bundled Update.exe assets to tmp dir + Log.Info("Extracting Update.exe resources"); + File.Copy(sourceFile, newAppHost); DumpPackageAssemblies(sourceFile, tmpdir); - // create new app host - var newAppHost = Path.Combine(tmpdir, sourceName + ".exe"); - HostWriter.CreateAppHost( - HelperExe.SingleFileHostPath, // input file - newAppHost, // output file - sourceName + ".dll", // entry point, relative to apphost - true, // isGui? - Path.Combine(tmpdir, sourceName + ".dll") // copy exe resources from? - ); - - // set new icon + // set new icon (which eradicates bundled assets) Log.Info("Patching Update.exe icon"); HelperExe.SetExeIcon(newAppHost, iconPath); + HostWriter.ResetBundle(newAppHost); - // create new bundle + // re-append bundled assets to exe + Log.Info("Re-packing Update.exe bundle"); var bundlerOutput = Path.Combine(tmpdir, "output"); Directory.CreateDirectory(bundlerOutput); var bundler = new Bundler( @@ -151,8 +145,6 @@ namespace Squirrel.CommandLine false, sourceName ); - - Log.Info("Re-packing Update.exe bundle"); var singleFile = GenerateBundle(bundler, tmpdir, bundlerOutput); // copy to requested location @@ -167,7 +159,7 @@ namespace Squirrel.CommandLine using (var memoryMappedPackage = MemoryMappedFile.CreateFromFile(packageFileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read)) { using (var packageView = memoryMappedPackage.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read)) { - var manifest = DotnetUtil.ReadManifest(packageView, bundleHeaderOffset); + var manifest = ReadManifest(packageView, bundleHeaderOffset); foreach (var entry in manifest.Entries) { Stream contents; diff --git a/src/Squirrel.CommandLine.Windows/HelperExe.cs b/src/Squirrel.CommandLine.Windows/HelperExe.cs index 60b0702a..ba394703 100644 --- a/src/Squirrel.CommandLine.Windows/HelperExe.cs +++ b/src/Squirrel.CommandLine.Windows/HelperExe.cs @@ -18,7 +18,6 @@ namespace Squirrel.CommandLine public static string UpdatePath => FindHelperFile("Update.exe", p => Microsoft.NET.HostModel.AppHost.HostWriter.IsBundle(p, out var _)); public static string StubExecutablePath => FindHelperFile("StubExecutable.exe"); - public static string SingleFileHostPath => FindHelperFile("singlefilehost.exe"); // private so we don't expose paths to internal tools. these should be exposed as a helper function private static string SignToolPath => FindHelperFile("signtool.exe"); diff --git a/src/Squirrel.CommandLine/HostModel/AppHost/HostWriter.cs b/src/Squirrel.CommandLine/HostModel/AppHost/HostWriter.cs index 3153a414..9863036f 100644 --- a/src/Squirrel.CommandLine/HostModel/AppHost/HostWriter.cs +++ b/src/Squirrel.CommandLine/HostModel/AppHost/HostWriter.cs @@ -209,8 +209,37 @@ namespace Microsoft.NET.HostModel.AppHost /// Check if the an AppHost is a single-file bundle /// /// The path of Apphost to check - /// An out parameter containing the offset of the bundle header (if any) /// True if the AppHost is a single-file bundle, false otherwise + public static void ResetBundle(string appHostFilePath) + { + byte[] bundleSignature = { + // 32 bytes represent the bundle signature: SHA-256 for ".net core bundle" + 0x8b, 0x12, 0x02, 0xb9, 0x6a, 0x61, 0x20, 0x38, + 0x72, 0x7b, 0x93, 0x02, 0x14, 0xd7, 0xa0, 0x32, + 0x13, 0xf5, 0xb9, 0xe6, 0xef, 0xae, 0x33, 0x18, + 0xee, 0x3b, 0x2d, 0xce, 0x24, 0xb3, 0x6a, 0xae + }; + + void ResetBundleHeader() + { + using (var memoryMappedFile = MemoryMappedFile.CreateFromFile(appHostFilePath)) + { + using (MemoryMappedViewAccessor accessor = memoryMappedFile.CreateViewAccessor()) + { + int position = BinaryUtils.SearchInFile(accessor, bundleSignature); + if (position == -1) + { + throw new PlaceHolderNotFoundInAppHostException(bundleSignature); + } + + accessor.WriteArray(position - sizeof(long), new byte[sizeof(long)], 0, sizeof(long)); + } + } + } + + RetryUtil.RetryOnIOError(ResetBundleHeader); + } + public static bool IsBundle(string appHostFilePath, out long bundleHeaderOffset) { byte[] bundleSignature = { diff --git a/vendor/singlefilehost.exe b/vendor/singlefilehost.exe deleted file mode 100644 index 307067b7..00000000 Binary files a/vendor/singlefilehost.exe and /dev/null differ