oleg-shilo / wixsharp

Framework for building a complete MSI or WiX source code by using script files written with C# syntax.
MIT License
1.13k stars 175 forks source link

Propagate bootstrapper installation directory to MSI #1682

Open Ceran0r opened 1 day ago

Ceran0r commented 1 day ago

Hi, I'm currently very unclear on how to use the installation location the user can set at runtime in the bootstrapper.

When creating a Bundle with SuppressOptions set to false, there is an "Options" button in the installation UI that will allow the user to enter a custom installation directory on their machine. However, that line is blank by default, and even if I fill something in manually, when the installation is completed, the installed files are at the location I specify within my ManagedProject. This seems logical to me, as I don't see how the entered value would propagate at runtime to the .msi created from that project that is called within the bootstrapper.

My question is this - how can I access and use that value within the ManagedProject, so that the user can determine its installation location at runtime?

I need to use a bootstrapper .exe, because alongside this program, several drivers need to be installed, which always go to a fixed location (so there is no need to change it), but the user must be able to determine the location of the "main" program. Any help, please?

Torchok19081986 commented 19 hours ago

Morning, AFAIK bootstrapper communicate with MSI over bundlevariables. There is sample in Src from oleg, where Installdir is set at start of bundle installation. ... Source\src\WixSharp.Samples\Wix# Samples\Bootstrapper\WixBootstrapper_UI

 var bootstrapper =
     new Bundle("My Product",
                new MsiPackage(productMsi)
                {
                    Id = "MyProductPackageId",
                    DisplayInternalUI = true,
                    MsiProperties = "USERINPUT=[UserInput];REGISTRYINPUT=[RegistryInput];"
                }     
               );

 bootstrapper.Variables = "UserInput=none; RegistryInput=none; UserInput2=none; RegistryInput2=none; ".ToStringVariables();

and in bootstrapper self

Bootstrapper.Engine.StringVariables["UserInput"] = UserInput;

This will set your UserInput Path as Installdir and translate / transfer bundle variable to msi and in msoi you can show or determine this as installdir. Only remember, this is for Wix V3, in Wix V4 are breaing changes and Wixsharp do something different in V4. AOT Compilation. Hope this helps.

Ceran0r commented 15 hours ago

Thanks for the quick help - the last line using Engine somewhat confuses me though, what if I'm not implementing my own bootstrapper UI but using the predefined one? What I'm doing so far is this

    private Bundle CreateBootstrapper()
    {
        var bundle = new Bundle(Name)
        {
            Version = Version,
            Manufacturer = Author,
            UpgradeCode = Guid,
            OutFileName = OutputFileName,
            IconFile = Icon.GetResourcePath(),
            Application =
            {
                LogoFile = Logo.GetResourcePath(),
                LogoSideFile = Banner.GetResourcePath(),
                ShowVersion = true,
                SuppressRepair = true
            }
        };
        if (AboutUrl is not null)
            bundle.AboutUrl = AboutUrl;
        bundle.Variables = "UserInput=none;".ToStringVariables(); // Based on first answer, also set in MSI properties
        return bundle;
    }

and then adding my MSI (and other executables for the drivers) to the bootstrapper's Chain.

Torchok19081986 commented 14 hours ago

engine is wix toolset engine / pipeline that executed burn installer with msi. Here you dont have to implement your own BA and you can rely on standard Wix Toolset BA Chain from start to end.
AFAIK Engine is always within Bundle. Bundle is exe with UI, which was created by wix toolset team, but @oleg-shilo did implementation of it in WixSharp and examples shows any possible scneario, how to use it. There is also Wix V3 template for BA Instatller. Just create test project and simulate some scenario , what do you want to achieve. Is easy way without corrupt your own original project. Need sometime, but with this you gain information for your BA and how to use it.

Ceran0r commented 13 hours ago

Thank you so much, I made it work using this sample.

All I had to do was the following:

var bundle = new Bundle(Name)
        {
            Version = Version,
            Manufacturer = Author,
            UpgradeCode = Guid,
            OutFileName = OutputFileName,
            IconFile = Icon.GetResourcePath(),
            Application =
            {
                LogoFile = Logo.GetResourcePath(),
                LogoSideFile = Banner.GetResourcePath(),
                ShowVersion = true,
                SuppressRepair = true
            }
        };
        if (AboutUrl is not null)
            bundle.AboutUrl = AboutUrl;
        bundle.Variables = [new Variable("InstallFolder", DefaultLocation) { Overridable = true }];

        return bundle;

in the bootstrapper and then

        return new MsiPackage(MsiPath)
        {
            Vital = IsCritical,
            MsiProperties = "INSTALLDIR=[InstallFolder]"
        };

in the package, and it works like a charm.

Torchok19081986 commented 13 hours ago

only one thing. INSTALLDIR Property exists always in MSI Packge. If Bundle do something with it, may you need some change here.

Ceran0r commented 12 hours ago

What do you mean?

Torchok19081986 commented 12 hours ago

AFAIK you dont have to explicit set INSTALLDIR for MSI. Bundle just execute MSI Package, means, INSTALLDIR will be evaluate / will be set in MSI self.

Ceran0r commented 12 hours ago

That's what I had so far, and it didn't work - if I omit MsiProperties = "INSTALLDIR=[InstallFolder]", it always goes to the "default" location I pass into it.

Torchok19081986 commented 12 hours ago

Then bundle do some changes by mapping this variables to MSI , and here if something not OK, you will need changes. Also upgrade need be more carefully tested. If you dont set Properties for show or hidden in ARP Info, it shows 2 entries. Bundle AND MSI.

Ceran0r commented 12 hours ago

I'll finish programming it out and get back to you with my findings!

Ceran0r commented 10 hours ago

As far as I can tell, this solution seems to work as intended, with uninstalling and upgrading included!