Closed tig closed 4 years ago
Charlie, just adding 3 lines to your setup.cs is unlikely to help 😄
WixSharp is an MSI builder and as such it is bound to the all MSI constraints/limitations. One of which is that MSI can only install a single product. You are trying to install two: .net and your product. The only thing that a single MSI allows you to do is to detect the presense of .NET Core but not to install it.
Thus it is a task for a bootstrapper, that would install .NET Core and then your MSI.
WixSharp supports two types of bootstrapping. MSI/WiX and NSIS. The code samples demonstrate both (WixBootsstrapper
and NsisBootstrapper
):
var bootstrapper =
new Bundle("My Product",
// new PackageGroupRef("NetFx40Web"),
new ExePackage(@"..\redist\dotNetFx40_Full_x86_x64.exe")
{
Name = "Microsoft .NET Framework 4.0",
InstallCommand = "/passive /norestart",
Permanent = true,
Vital = true,
DetectCondition = "Netfx4FullVersion AND (NOT VersionNT64 OR Netfx4x64FullVersion)",
Compressed = true
},
new MsiPackage("<path_to_your_msi>"),
. . .
bootstrapper.Build();
Thus the WiX bootstrapper sample above shows to to embed .NET 4.0 setup executable in your bootstrapper. The commented out code shows how to include .NET 4.0 web setup that is already developed by WiX team.
Both techniques can be extended to .NET Core though you will need to find out how much of prework is done by WiX team. If none (e.g. detect condition is not available for .net core) then your best chance is to embed the .NET core setup executable as above but instead of the DetectCondition
use custom BA where you can implement detection by yourself. WixBootstrapper_NoUI
sample shows how to create a custom BA.
Alternative bootstrapper NSIS may in fact help you to solve the problem in a simpler way. I am not fluent in NSIS so cannot halp you much but Tigran @geghamyan (is the one who contributed NSIS WixSharp binding to NSIS bootstrapper) probably can.
Super helpful. Thanks.
I found this: https://github.com/wixtoolset/issues/issues/6099
Now all I need to do is to figure out how to add the PackageGroupRef
XML definition found there (https://github.com/wixtoolset/issues/issues/6099#issuecomment-588698243) to a wixsharp
project...
Oh you can totally add ExePackage
. It's fully supported:
new Bundle("My Product Suite",
new ExePackage(@"Samples\Setup1.exe")
{
Id = "package_net_core",
Name = "aspnetcore-runtime-3.1.2-win-x64.exe",
InstallCommand = "/install /quiet /norestart /log \"[AspNetCoreRuntime31Log]\"",
RepairCommand = "/repair /quiet /norestart /log \"[AspNetCoreRuntime31Log]\"",
UninstallCommand = "/uninstall /quiet /norestart /log \"[AspNetCoreRuntime31Log]\"",
Permanent = true,
. . .
RemotePayloads = new[]
{
new RemotePayload
{
CertificatePublicKey="6ADD0C9D1AC70DA3668644B1C78884E82E3F3457",
CertificateThumbprint="711AF71DC4C4952C8ED65BB4BA06826ED3922A32",
Description="Microsoft ASP.NET Core 3.1.2 - Shared Framework",
Hash="B8EDDD91C0DFD9E47EB7DD7EFED9541340607ADC",
ProductName="Microsoft ASP.NET Core 3.1.2 - Shared Framework",
Size=7812680,
Version="3.1.2.20068".ToRawVersion()
}
},
},
new MsiPackage(productMsi)
. . .
Hi Charlie, Building a fully-rounded, correctly handing upgrades, preventing downgrades etc burn bootstrapper with a custom UI is not a trivial task. We have products built with the wix burn bootstrapper and with the NSIS bootstrapper and I can tell you from experience we had to add much more code to the wix burn samples to tailor it to our needs.
If you are okay with increasing the size of your final setup package, you can use NSIS bootstrapper and embed the dotnetcore package into it.
Here's what I ended up doing, since I already have a WPF EmbeddedUI:
Gets me 95% of where I need to be for this project:
private bool IsDotNetCore31Installed() {
try {
RegistryKey localMachine64 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey lKey = localMachine64.OpenSubKey(@"SOFTWARE\dotnet\Setup\InstalledVersions\x64\sharedhost\", false);
Version installed = new Version((string)lKey.GetValue("Version"));
Version required = new Version(Session["RequiredDotNetCoreVersion"]);
return installed.CompareTo(required) > 0;
}
catch {
return false;
}
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
if (IsDotNetCore31Installed()) {
}
else {
// Configure message box
string message = $"winprint requires .NET Core {Session["RequiredDotNetCoreVersion"]} to run.\n\nClick OK to download and install.";
string caption = this.Title;
MessageBoxButton buttons = MessageBoxButton.OK;
MessageBoxImage icon = MessageBoxImage.Information;
MessageBoxResult defaultResult = MessageBoxResult.OK;
// Show message box
MessageBoxResult result = MessageBox.Show(this, message, caption, buttons, icon, defaultResult);
Process.Start("https://dotnet.microsoft.com/download/dotnet-core/current/runtime");
}
}
Yes, it basically similar to an approach from here: wixsharp\Source\src\WixSharp.Samples\Wix# Samples\Bootstrapper\Simplified Bootstrapper
Just take into account that UI and your code won't execute if you run the installer in the silent mode.
What you need to do is:
I've made some extensions for wixsharp. Altough, my project depends on .net core bundled with hosting, you may need alter the registry search to suit your needs.
Hope I have time to clean up my project soon and share it on github, here are at least some help for now:
var bootstrapper = new Bundle("product name here")
{
UpgradeCode = BootstrapperUpgradeCode,
Version = version,
Chain = new List<ChainItem>()
{
// TODO: add the .net core online dependency with condition set to "NOT DOT_NET_CORE_AND_HOSTING_DETECTED"
// TODO: add your MSI project
}
};
bootstrapper
.HideFromAddRemovePrograms()
.SuppressApplicationOptionsUI()
.IncludeWixUtilExtension()
.AddRegistrySearchAspNetCoreExists("DOT_NET_CORE_AND_HOSTING_DETECTED")
The extension methods used above are available here: https://gist.github.com/yurislav/d5d22097870f55657b15c78557417475
@yurislav, just by looking at this:
bootstrapper
.HideFromAddRemovePrograms()
.SuppressApplicationOptionsUI()
.IncludeWixUtilExtension()
.AddRegistrySearchAspNetCoreExists(. . .)
I can tell that you have created an interesting extension suite.
Is it something that you would like to become a part of WixSharp codebase?
@yurislav, just by looking at this:
bootstrapper .HideFromAddRemovePrograms() .SuppressApplicationOptionsUI() .IncludeWixUtilExtension() .AddRegistrySearchAspNetCoreExists(. . .)
I can tell that you have created an interesting extension suite.
Is it something that you would like to become a part of WixSharp codebase?
Sure, I will separate my project-specific code with these extensions as an public repository and you can integrate relevant methods to wixsharp, because there are also temporary hotfixes for already resolved bugs or missing features.
Great, thank you
Hi @oleg-shilo, as I promised, my project-specific code is separated and rest is on github repo. ~I'll try to add readme with examples soon~.
Great. Thank you. Will have a look.
It does seem like a comprehensive extension to the default WixSharp functionality.
I am happy to include it to WixSharp codebase and I will indicate you as a contributor. But...
Considering the scale of your contribution, are you sure that you don't want to make it into your own dedicated NuGet package? IE WixSharp.extensions
.
Yes, that's what I already did (https://www.nuget.org/packages/NineDigit.WixSharpExtensions). Leaving the code as truly separated "extension" makes sense too.
Fantastic. Then I will put the recommendation and the link in one of the WixSharp main pages. Txs
Great, thank you :)
This should be simple. I've searched the Internet and read as much as I could, but I can't find anything simple. I can't be the only person using
wixsharp
to install adotnetcore3.1
based Windows app and needing the installer to ensuredotnetcore3.1
is installed.Perhaps I'm just missing a key piece of understanding. What I'm hoping for is someone can literally just say "Charlie, just add the following 3 lines to your
setup.cs
file:Here's my
wixsharp
installer: