Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WiX: How to override "C:\Program Files (x86)" on x64 machine in WixUI_Advanced sequence?

I'm using WixUI_Advanced sequence to allow users pick per-machine or per-user installation and change destination folder. My WiX project is intended to produce both x86 and x64 MSIs (I'm using WiX Tips and Tricks recommendations). I also keep the app installation folder in the registry for major upgrades (I use APPLICATIONFOLDER property and directory ID -- instead of INSTALLLOCATION -- per WixUI_Advanced requirements).

There is a bug in WixUI_Advanced sequence that causes the Destination Folder dialog to display the app folder under C:\Program Files (x86) instead of C:\Program Files when running on a 64-bit machine, even when the code correctly sets app folder to ProgramFiles64Folder property. The bug tracker comment suggests using the SetDirectory element to set the value of APPLICATIONFOLDER, but there is no example explaining how to do this. When I tried, it did dot make any difference (I also found a number of posts recommending using a custom action to set APPLICATIONFOLDER, but none worked for me). Does anyone know how to make WixUI_Advanced sequence display correct 'Program Files' folder on a 64-bit system (and also show the originally selected folder during major upgrades)?

If it helps, I'll provide sample WXS snippets, but they pretty much follow the recommendations from the StackOverflow's WiX Tips and Tricks post. Also, my 64-bit MSI package is indeed a 64-bit package (I have the package and components marked as 'x64"; and it does not run on 32-bit platforms). I'm using WiX 3.6 and Visual Studio 2010.

CODE SAMPLE:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

<Product 
    Id="81955f17-31f3-4e51-8294-372f96141c00" 
    Name="WiX64BitDemo" 
    Language="1033" 
    Version="1.0.0.0" 
    Manufacturer="Test" 
    UpgradeCode="5bed9777-bea6-4dc3-91d7-5dd93819563a">

<Package 
    InstallerVersion="300" 
    Compressed="yes"
    InstallScope="perMachine"
    Platform="x64" />

<MajorUpgrade 
    AllowSameVersionUpgrades="no"
    DowngradeErrorMessage="Can't downgrade."
    Schedule="afterInstallInitialize" />

<Media 
    Id="1" 
    Cabinet="media1.cab" 
    EmbedCab="yes" />

<Property Id="APPLICATIONFOLDER" Secure="yes">
    <RegistrySearch Id="FindInstallLocation"
        Root="HKLM"
        Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[WIX_UPGRADE_DETECTED]"
        Name="InstallLocation"
        Type="raw"
        Win64="yes" />
</Property>

<Property Id="ApplicationFolderName" Value="WiX64BitDemo" />
<Property Id="WixAppFolder" Value="WixPerMachineFolder" />

<SetDirectory 
    Id="APPLICATIONFOLDER" 
    Value="[ProgramFiles64Folder][ApplicationFolderName]">APPLICATIONFOLDER=""</SetDirectory>

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="ProgramFiles64Folder">
        <Directory Id="APPLICATIONFOLDER" Name="WiX64BitDemo">
            <Component 
                Id="ReadmeComponent" 
                Guid="*" 
                Win64="yes">

                <File
                    Id="ReadmeFile"
                    Name="readme.txt"
                    Source="$(var.ProjectDir)readme.txt"
                    KeyPath="yes"/>
            </Component>
        </Directory>
    </Directory>
</Directory>

<Feature Id="ProductFeature" Title="WiX64BitDemo" Level="1">
    <ComponentRef Id="ReadmeComponent" />
</Feature>

<UI Id="UISequence">
    <UIRef Id="WixUI_Advanced"/>
</UI>

</Product>
</Wix>

Many thanks to Sascha Beaumont for solving this problem. Here is the working sample:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product
    Id="81955f17-31f3-4e51-8294-372f96141c00"
    Name="WiX64BitDemo" 
    Language="1033" 
    Version="1.0.0.0" 
    Manufacturer="Test" 
    UpgradeCode="5bed9777-bea6-4dc3-91d7-5dd93819563a">

<Package 
    InstallerVersion="300" 
    Compressed="yes"
    InstallScope="perMachine"
    Platform="x64" />

<MajorUpgrade 
    AllowSameVersionUpgrades="no"
    DowngradeErrorMessage="Can't downgrade."
    Schedule="afterInstallInitialize" />

<Media 
    Id="1" 
    Cabinet="media1.cab" 
    EmbedCab="yes" />

<Property Id="APPLICATIONFOLDER" Secure="yes">
    <RegistrySearch Id="FindInstallLocation"
        Root="HKLM"
        Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[WIX_UPGRADE_DETECTED]"
        Name="InstallLocation"
        Type="raw"
        Win64="yes" />
</Property>

<Property Id="ApplicationFolderName" Value="WiX64BitDemo" />
<Property Id="WixAppFolder" Value="WixPerMachineFolder" />

<SetDirectory 
    Id="APPLICATIONFOLDER" 
    Value="[ProgramFiles64Folder][ApplicationFolderName]">APPLICATIONFOLDER=""</SetDirectory>

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="ProgramFiles64Folder">
        <Directory Id="APPLICATIONFOLDER" Name="WiX64BitDemo">
            <Component 
                Id="ReadmeComponent" 
                Guid="*" 
                Win64="yes">

                <File
                    Id="ReadmeFile"
                    Name="readme.txt"
                    Source="$(var.ProjectDir)readme.txt"
                    KeyPath="yes"/>
            </Component>
        </Directory>
    </Directory>
</Directory>

<Feature Id="ProductFeature" Title="WiX64BitDemo" Level="1">
    <ComponentRef Id="ReadmeComponent" />
</Feature>

<UI Id="UISequence">
    <UIRef Id="WixUI_Advanced"/>
</UI>

<CustomAction
        Id="OverwriteWixSetDefaultPerMachineFolder"
        Property="WixPerMachineFolder"
        Value="[APPLICATIONFOLDER]"
        Execute="immediate"
/>

<CustomAction 
    Id="SetARPINSTALLLOCATION" 
    Property="ARPINSTALLLOCATION" 
    Value="[APPLICATIONFOLDER]"  
/>

<InstallUISequence>
    <Custom Action="OverwriteWixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />
</InstallUISequence>

<InstallExecuteSequence>
    <Custom Action="OverwriteWixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />
    <Custom Action="SetARPINSTALLLOCATION" After="InstallValidate"/>
</InstallExecuteSequence>

</Product>
</Wix>
like image 966
Alek Davis Avatar asked Mar 29 '11 22:03

Alek Davis


People also ask

What is Targetdir WiX?

The element with the id TARGETDIR is required by the Windows Installer and is the root of all directory structures for your installation. Every WiX project will have this directory element.

What is WiX Bootstrapper?

The bootstrapper application DLL is responsible for displaying UI to the end-user and directs the Burn engine when to carry out download, install, repair and uninstall actions.

What are WiX fragments?

The Fragment element is the building block of creating an installer database in WiX. Once defined, the Fragment becomes an immutable, atomic unit which can either be completely included or excluded from a product.


1 Answers

Something like this would probably do the trick:

<MajorUpgrade AllowSameVersionUpgrades="yes"
          DowngradeErrorMessage="Can't downgrade."
          Schedule="afterInstallInitialize" />


<Property Id="APPLICATIONFOLDER" Secure="yes">
    <RegistrySearch Id="FindInstallLocation"
        Root="HKLM"
        Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[WIX_UPGRADE_DETECTED]"
        Name="InstallLocation"
        Type="raw"
        Win64="yes" />
</Property>


<CustomAction Id="Overwrite_WixSetDefaultPerMachineFolder" Property="WixPerMachineFolder" Value="[ProgramFiles64Folder][ApplicationFolderName]" Execute="immediate" />
<InstallUISequence>
    <Custom Action="Overwrite_WixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />
</InstallUISequence>
<InstallExecuteSequence>
    <Custom Action="Overwrite_WixSetDefaultPerMachineFolder" After="WixSetDefaultPerMachineFolder" />
</InstallExecuteSequence>

<SetProperty Id="ARPINSTALLLOCATION" Value="[APPLICATIONFOLDER]" After="CostFinalize" />

UPDATE: SetDirectory schedules the action prior to WixSetDefaultPerMachineFolder - code updated for manually scheduled elements to schedule between WixSetDefaultPerMachineFolder and WixSetPerMachineFolder. Tested OK with OP sample code under Win7 x64

UPDATE2: Added action to set ARPINSTALLOCATION as http://robmensching.com/blog/posts/2011/1/14/ARPINSTALLLOCATION-and-how-to-set-it-with-the-WiX-toolset

like image 131
saschabeaumont Avatar answered Sep 22 '22 05:09

saschabeaumont