oleg-shilo / wixsharp

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

Bootstrap condition via variable #1219

Closed Zerpico closed 2 years ago

Zerpico commented 2 years ago

Bundle has the ability to set a condition for installing the package through a search in the registry.

example:


const string conditionName = "PostgresFound";

bundle.AddWixFragment("Wix/Bundle",
    new UtilRegistrySearch
    {
        Root = RegistryHive.LocalMachine,
        Key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PostgreSQL 10",
        Value = "InstallLocation",
        Win64 = true,
        Result = SearchResult.exists,
        Variable = conditionName
    });

bundle.Chain.Add(new ExePackage(Path.Combine(redistDir, "postgresql-10.21-1-windows-x64.exe"))
{
    InstallCommand ="--mode unattended --unattendedmodeui none --servicename \"postgres\"",
    UninstallCommand = "--mode unattended --disable-components server,pgAdmin,commandlinetools",
    DetectCondition = $"{conditionName}<>0",
    PerMachine = true,
    Vital = true,
    Permanent = true,
    Compressed = Compressed
});

Is there a similar possibility for setting condition from session variable?

I want to add a checkbox to the theme bundle, which will mean whether to install some feature or not

Zerpico commented 2 years ago

This is how i did it:

In theme.xml i add MyCheckbox

    <Page Name="Install">
        <Richedit Name="EulaRichedit" X="11" Y="80" Width="-11" Height="-110" TabStop="yes" FontId="0" HexStyle="0x800000" />
        <Checkbox Name="EulaAcceptCheckbox" X="11" Y="270" Width="300" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
        <Checkbox Name="MyCheckbox" X="11" Y="290" Width="300" Height="17" TabStop="yes" FontId="3" >#(loc.MyCheckLabel)</Checkbox>
        <Button Name="OptionsButton" X="-201" Y="-11" Width="85" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button>
        <Button Name="InstallButton" X="-111" Y="-11" Width="85" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
        <Button Name="WelcomeCancelButton" X="-21" Y="-11" Width="85" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
    </Page>

Then added in bundle a property with the same name as the checkbox

bundle.Variables = new[] {
    new Variable("MyCheckbox", "0", VariableType.numeric) { Overridable = true }
};

And then add Msi package with install condition:

bundle.Chain.Add(new MsiPackage(msiPath) { Compressed = Compressed, InstallCondition = "MyCheckbox<>0" });
oleg-shilo commented 2 years ago

How did you include "theme.xml" in the project? Can you share your solution? I would like to bring support for this feature.

Zerpico commented 2 years ago

@oleg-shilo included the theme file as in the example. Add AttributesDefinition in Application :

var itemsDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ?? string.Empty;
var bundle = new Bundle(bundleName)
{
    Manufacturer = "MyCompany",
    UpgradeCode = new Guid(guid),
    Version = version,
    IconFile = Path.Combine(itemsDir, iconName),
    Application = new LicenseBootstrapperApplication
    {
        LicensePath = Path.Combine(itemsDir, "license.rtf"),
        LocalizationFile = Path.Combine(itemsDir, "mbapreq.wxl"),
        //this atribute add theme
        AttributesDefinition = $"ThemeFile={Path.Combine(itemsDir, "RtfTheme.xml")}; ShowVersion=yes; ShowFilesInUse=yes",
        LogoFile = Path.Combine(itemsDir, "logo64.png"),                    
    },
    SuppressWixMbaPrereqVars = true
};

bundle.Variables = new[] {
    new Variable("MyCheckbox", "0", VariableType.numeric) { Overridable = true }
};

bundle.Chain.Add(new MsiPackage(msiPath) { Compressed = Compressed, InstallCondition = "MyCheckbox<>0" });
oleg-shilo commented 2 years ago

Excellent. Thank you. Will add ThemeFile property. I will reopen this issue as an Enhancement issue for release tracking purposes.

oleg-shilo commented 2 years ago

Silly me, it is already there 😄
image

Zerpico commented 2 years ago

By the way, something else might be useful. On the options page, I wanted to see the path to the installation of my main msi. But the EditBox is empty by default. I added an override variable to the bundle.

string installDir = Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%"), CompanyName, AppName);

var bundle = new Bundle(bundleName)
{
  //some properties here
};

bundle.Variables = new[] {
     new Variable("MyInstallDir", installDir) { Overridable = true }
};

bundle.Chain.Add(new MsiPackage(msiPath) { MsiProperties = "INSTALLDIR=[MyInstallDir]" });

And set for Editbox value is variable [MyInstallDir] in theme.xml

<Page Name="Options">
    <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Text>
    <Text X="11" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OptionsLocationLabel)</Text>
    <Editbox Name="FolderEditbox" X="11" Y="143" Width="-91" Height="21" FontId="3" FileSystemAutoComplete="yes">[MyInstallDir]</Editbox>
    <Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" FontId="3">#(loc.OptionsBrowseButton)</Button>
    <Button Name="OptionsOkButton" X="-116" Y="-11" Width="95" Height="30" FontId="0">#(loc.OptionsOkButton)</Button>
    <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="95" Height="30" FontId="0">#(loc.OptionsCancelButton)</Button>
</Page>

This adds in the option page the default path is not empty

image

oleg-shilo commented 2 years ago

Great. Txs. I am adding your sample in the samples library now.

And the next question: "where you defined MyCheckLabel?". Is it coming from the custom WXL?

Zerpico commented 2 years ago

Change InstallDir not work in bundle 😞 I am attaching a project with an example of MyCheckBox and InstallDir WixSharpBootstrap_Sample.zip

oleg-shilo commented 2 years ago

Hm, indeed it does not. Though the whole idea of "options" page is to push user choice to the individual installers. Will try to rectify it.

This post makes me think that it is a bug in the Burn: https://stackoverflow.com/questions/40882567/why-cant-the-install-location-be-selected-from-browse-directory-panel-in-burn

oleg-shilo commented 2 years ago

It appears that 'options' page uses a special built-in variable InstallFolder for tunnelling user-selected folder.

Your code needs to be changed like this:

bundle.Chain.Add(new MsiPackage(msiPath) { MsiProperties = "INSTALLDIR=[InstallFolder]" });

I have also updated the sample with your scenario: 84ce7ff