Search code examples
wixwindows-installer

Wix bootstrapper won't read LocalAppDataFolder properly if they don't click the Options button


I'm using the BalExtension with the WixStandardBootstrapperApplication.HyperlinkSidebarLicense

I want to always install the application the the local App Data Folder of the current user if they did not change the installation directory in the options page. It works fine when I follow through the installation WHEN I CLICK THE OPTIONS BUTTON and click OK

But if I follow through the installer without clicking the options page. It will get the admin App Data Folder instead.

I have the burn.wxs setup like this

<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
    xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
    xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
    <Bundle
    Name="My Installer"
    Version="1.0.0.0"
    IconSourceFile="icon.ico"
    Manufacturer="Me">

        <Variable Name="InstallFolder" Type="string" Value="[LocalAppDataFolder]"/>
       ...
        <Chain>
            <ExePackage
                SourceFile="PreReqDrivers.exe"
                InstallCommand="/S"
                UninstallCommand="/S"
                PerMachine="yes">
                ...
            </ExePackage>
            <MsiPackage SourceFile="Main.msi">
                <MsiProperty Name="INSTALLDIR" Value="[InstallFolder]\Test\" />
            </MsiPackage>
        </Chain>
    </Bundle>
    ...
</Wix>

Is there a way to always default to the current user's local app data regardless if they click the options button or not.

I have gathered 2 logs when I install it without touching the options button and when touching the options button.

OptionButton Not Touched:

[1C0C:2CD4][2020-07-09T16:25:45]i001: Burn v3.14.0.4118, Windows v10.0 (Build 18363: Service Pack 0), path: C:\Users\CURRENTUSER\My Installer.exe
[1C0C:2CD4][2020-07-09T16:25:45]i000: Initializing string variable 'InstallFolder' to value '[LocalAppDataFolder]'
...
[1C0C:2CD4][2020-07-09T16:25:53]i201: Planned package: PreReqDrivers.exe, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: None
[1C0C:2CD4][2020-07-09T16:25:53]i201: Planned package: Main.msi, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: Register
[1C0C:2CD4][2020-07-09T16:25:53]i299: Plan complete, result: 0x0
[1C0C:2CD4][2020-07-09T16:25:53]i300: Apply begin
[1C0C:2CD4][2020-07-09T16:25:53]i010: Launching elevated engine process.
[1C0C:2CD4][2020-07-09T16:25:58]i011: Launched elevated engine process.
[1C0C:2CD4][2020-07-09T16:25:58]i012: Connected to elevated engine.
[26FC:48FC][2020-07-09T16:25:58]i358: Pausing automatic updates.
[26FC:48FC][2020-07-09T16:25:58]i359: Paused automatic updates.
[26FC:48FC][2020-07-09T16:25:58]i360: Creating a system restore point.
[26FC:48FC][2020-07-09T16:25:58]i361: Created a system restore point.
...
[26FC:48FC][2020-07-09T16:26:00]i301: Applying execute package: PreReqDrivers.exe, action: Install, path: C:\ProgramData\Package Cache\[GUID?]\PreReqDrivers.exe, arguments: '"C:\ProgramData\Package Cache\[GUID?]\PreReqDrivers.exe" /S'
[1C0C:2CD4][2020-07-09T16:26:05]i319: Applied execute package: PreReqDrivers.exe, result: 0x0, restart: None
[26FC:48FC][2020-07-09T16:26:05]i323: Registering package dependency provider: {...GUID...}, version: 1.0, package: Main.msi
[26FC:48FC][2020-07-09T16:26:05]i301: Applying execute package: Main.msi, action: Install, path: C:\ProgramData\Package Cache\{...GUID...}v1.0\Main.msi, arguments: ' ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="7" INSTALLDIR="C:\Users\admin\AppData\Local\\Test\"'
[1C0C:2CD4][2020-07-09T16:26:13]i319: Applied execute package: Main.msi, result: 0x0, restart: None
[26FC:48FC][2020-07-09T16:26:13]i325: Registering dependency: {...GUID...} on package provider: {...GUID...}, package: Main.msi
...
[1C0C:2CD4][2020-07-09T16:26:14]i410: Variable: InstallFolder = C:\Users\CURRENTUSER\AppData\Local\
[1C0C:2CD4][2020-07-09T16:26:14]i410: Variable: LocalAppDataFolder = C:\Users\CURRENTUSER\AppData\Local\
...
[1C0C:2CD4][2020-07-09T16:26:14]i007: Exit code: 0x0, restarting: No

OptionButton Touched:

[3FE8:16B8][2020-07-09T16:30:53]i001: Burn v3.14.0.4118, Windows v10.0 (Build 18363: Service Pack 0), path: C:\Users\CURRENTUSER\AppData\Local\Temp\{15330765-B5AB-491D-84A2-D39A5A851BF6}\.cr\My Installer.exe
[3FE8:16B8][2020-07-09T16:30:53]i000: Initializing string variable 'InstallFolder' to value '[LocalAppDataFolder]'
...
[3FE8:16B8][2020-07-09T16:30:59]i201: Planned package: PreReqDrivers.exe, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: None
[3FE8:16B8][2020-07-09T16:30:59]i201: Planned package: Main.msi, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: Register
[3FE8:16B8][2020-07-09T16:30:59]i299: Plan complete, result: 0x0
[3FE8:16B8][2020-07-09T16:30:59]i300: Apply begin
[3FE8:16B8][2020-07-09T16:30:59]i010: Launching elevated engine process.
[3FE8:16B8][2020-07-09T16:31:03]i011: Launched elevated engine process.
[3FE8:16B8][2020-07-09T16:31:03]i012: Connected to elevated engine.
[36D8:36DC][2020-07-09T16:31:03]i358: Pausing automatic updates.
[36D8:36DC][2020-07-09T16:31:03]i359: Paused automatic updates.
[36D8:36DC][2020-07-09T16:31:03]i360: Creating a system restore point.
[36D8:36DC][2020-07-09T16:31:03]i361: Created a system restore point.
...
[36D8:36DC][2020-07-09T16:31:05]i301: Applying execute package: PreReqDrivers.exe, action: Install, path: C:\ProgramData\Package Cache\[GUID?]\PreReqDrivers.exe, arguments: '"C:\ProgramData\Package Cache\[GUID?]\PreReqDrivers.exe" /S'
[3FE8:16B8][2020-07-09T16:31:10]i319: Applied execute package: PreReqDrivers.exe, result: 0x0, restart: None
[36D8:36DC][2020-07-09T16:31:10]i323: Registering package dependency provider: {...GUID...}, version: 1.0, package: Main.msi
[36D8:36DC][2020-07-09T16:31:10]i301: Applying execute package: Main.msi, action: Install, path: C:\ProgramData\Package Cache\{...GUID...}v1.0\Main.msi, arguments: ' ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="7" INSTALLDIR="C:\Users\CURRENTUSER\AppData\Local\\Test\"'
[3FE8:16B8][2020-07-09T16:31:18]i319: Applied execute package: Main.msi, result: 0x0, restart: None
[36D8:36DC][2020-07-09T16:31:18]i325: Registering dependency: {...GUID...} on package provider: {...GUID...}, package: Main.msi
...
[3FE8:16B8][2020-07-09T16:31:19]i410: Variable: InstallFolder = C:\Users\CURRENTUSER\AppData\Local\
[3FE8:16B8][2020-07-09T16:31:19]i410: Variable: LocalAppDataFolder = C:\Users\CURRENTUSER\AppData\Local\
...
[3FE8:16B8][2020-07-09T16:31:19]i007: Exit code: 0x0, restarting: No

Solution

  • For some reason, when I added this directorySearch before the <Chain>

            <util:DirectorySearch
                Variable="RealInstallFolder"
                Path="[InstallFolder]"/>
    

    Then changed my <MsiPackage> to

                <MsiPackage
                    SourceFile="Main.msi"
                    InstallCondition="NOT (RealInstallFolder = &quot;&quot;)">
                    <MsiProperty Name="INSTALLDIR" Value="[RealInstallFolder]\Test\" />
                </MsiPackage>
    

    Logs is now showing

    [4F94:2A4C][2020-07-10T10:31:50]i000: Setting string variable 'RealInstallFolder' to value 'C:\Users\CURRENTUSER\AppData\Local\'
    [4F94:22AC][2020-07-10T10:31:57]i000: Setting string variable 'InstallFolder' to value 'C:\Users\CURRENTUSER\AppData\Local\'
    [4F94:2A4C][2020-07-10T10:32:34]i052: Condition 'NOT (RealInstallFolder = "")' evaluates to true.
    ...
    [4F94:2A4C][2020-07-10T10:32:34]i201: Planned package: PreReqDrivers.exe, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: None
    [4F94:2A4C][2020-07-10T10:32:34]i201: Planned package: Main.msi, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: Register
    ...
    [0BD0:3E58][2020-07-10T10:32:45]i301: Applying execute package: Main.msi, action: Install, path: C:\ProgramData\Package Cache\{...GUID...}v1.0\Main.msi, arguments: ' ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="7" INSTALLDIR="C:\Users\CURRENTUSER\AppData\Local\\Test\"'
    

    So to fully solve my problem here's what I did: I removed the Variable declaration

    <Variable Name="InstallFolder" Type="string" Value="[LocalAppDataFolder]"/>
    

    I added TWO DirectorySearch

            <util:DirectorySearch
                Id="InitialDirectorySearch"
                Variable="InstallFolder"
                Path="[LocalAppDataFolder]"
                />
            <util:DirectorySearch
                Id="SecondDirectorySearch"
                After="InitialDirectorySearch"
                Variable="DefaultInstallFolder"
                Path="[InstallFolder]"
                />
    

    I also modified the chain to include TWO MsiPackage

                <MsiPackage
                    Id="DefaultPackage"
                    SourceFile="Main.msi"
                    InstallCondition="NOT (DefaultInstallFolder = &quot;&quot;) AND DefaultInstallFolder ~= InstallFolder">
                    <MsiProperty Name="INSTALLDIR" Value="[DefaultInstallFolder]\Test\" />
                </MsiPackage>
                <MsiPackage
                    Id="ModifiedPackage"
                    SourceFile="Main.msi"
                    InstallCondition="NOT (DefaultInstallFolder = &quot;&quot;) AND NOT (DefaultInstallFolder ~= InstallFolder)">
                    <MsiProperty Name="INSTALLDIR" Value="[InstallFolder]\Test\" />
                </MsiPackage>
    

    This solution now properly sets the INSTALLDIR to the local app data folder even though they didn't open the options page. This also handles if they decided to change the directory on the options. The first solution broke when the user changes the directory folder and it was still pointing to their local app data folder.

    I guess the compiler is optimizing on the previous build and will only set the InstallFolder Variable only after it detects that the InstallFolder changed on the options page OR when it is being used by the MsiProperty