Aaron Stebner's WebLog

Thoughts about setup and deployment issues, WiX, XNA, the .NET Framework and Visual Studio

Example WiX-based setup that can be used to build both 32-bit and 64-bit MSIs

Example WiX-based setup that can be used to build both 32-bit and 64-bit MSIs

  • Comments 20

I previously posted an example that allows you to build a WiX-based MSI that will install a Windows Vista Media Center application and create a custom start menu strip.  However, there is a limitation in this example (that was pointed out in this post on the Media Center Sandbox discussion forum) that affects the ability to install the application on 64-bit operating systems.  This blog post describes the limitations in my previous sample and presents a modified version of that sample that will allow you to build both 32-bit and 64-bit MSIs in order to work around the limitations.

Description of the problem with my previous example

As this forum post describes, you have to directly set registry entries in order to add custom strips to the Media Center start menu (which means that you have to author RegistryKey and RegistryValue elements in WiX).  However, if you create a 32-bit MSI and then try to install it on a 64-bit OS, the registry entries will get written to the WOW64 hive (HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft).  The 64-bit version of Windows Vista Media Center looks in the 64-bit registry hive and not the WOW64 registry hive when looking for custom start menu strips to load.  Therefore, the custom start menu strip will not appear in the Media Center start menu on a 64-bit OS in my previous example.

Example that can be used to solve this problem

To solve this issue, it is necessary to create separate 32-bit and 64-bit installers.  It is a little bit tricky to configure all of the settings and attributes that are necessary to create a 64-bit MSI just by reading through WiX and Windows Installer documentation, so I decided to create a WiX 3.0-based example that can be used to build 32-bit and 64-bit MSIs from the same WiX source (WXS) file.

You can download this example from http://cid-27e6a35d1a492af7.skydrive.live.com/self.aspx/Blog%7C_Tools/start%7C_menu%7C_strip%7C_setup%7C_example%7C_with%7C_64bit.zip.  I started from my previous 32-bit-only example, and added 64-bit build support.  While this sample happens to install a Windows Vista Media Center application, it is intended to help demonstrate the general concepts required to create 64-bit MSIs in WiX.

Changes made in this example to enable 64-bit builds

The new sample includes a single WXS file that is processed twice in order to build 2 different MSIs (one 32-bit and one 64-bit).  In order to create a single WXS file that can build both types of MSI, I introduced a WiX pre-processor variable to pass in the name of the processor architecture, and then I added some if/then/else blocks to conditionally set some of the necessary MSI attributes based on whether the MSI being created will be 32-bit or 64-bit.

If you look in the setup.wxs file in the example I posted, you can see all of the changes that I made to enable building a 64-bit MSI by looking for sections of the file that are enclosed in if statements such as the following:

<?if $(var.ProcessorArchitecture)=x64 ?>
    <Package Description="!(loc.Package_Description)" Comments="!(loc.Package_Comments)" InstallerVersion="200" Compressed="yes" Platforms="x64" />
<?else ?>
    <Package Description="!(loc.Package_Description)" Comments="!(loc.Package_Comments)" InstallerVersion="200" Compressed="yes" />
<?endif ?>

In order to set the ProcessorArchitecture variable, I added the following command line parameter when calling candle.exe to compile the WXS file:

"%WIX_BUILD_LOCATION%\candle.exe" setup.wxs -dProcessorArchitecture=%PROCARCH% -out "setup_%PROCARCH%.wixobj"

In addition, I added a second set of commands to call candle.exe and light.exe twice - one with the ProcessorArchitecture value set to x86 and the other with the ProcessorArchitecture value set to x64.

Specific differences between a 32-bit MSI and a 64-bit MSI

The following are the changes that I made in order to be able to create both 32-bit and 64-bit MSIs in WiX:

  • I created a unique product code for the x64 MSI that is different from the x86 MSI
  • In the Package element, the Platforms attribute must be set to the proper 64-bit operating system so that Windows Installer will recognize it as a 64-bit MSI.  In my example, I am creating an x64 MSI, so I set the Platforms value to "x64" for the 64-bit MSI, and left it blank (the default value) for the 32-bit MSI
  • I created a different default directory structure for each processor architecture.  The 64-bit MSI will install under the ProgramFiles64Folder and the 32-bit MSI will install under the ProgramFilesFolder by default.  This is necessary because Windows Installer requires 64-bit components to install under a 64-bit directory by default
  • I created a unique set of 64-bit components by copying the original set of 32-bit components, updating the Id values to be different than the 32-bit Id values, creating unique Guid values and adding the element Win64="yes" to indicate that these components are 64-bit.  A component must be marked as Win64="yes" in order to cause registry entries to be written under the 64-bit registry hive instead of the WOW64 registry hive
  • In order to prevent the 32-bit MSI from installing on a 64-bit OS (which will work by default, but that we do not want to work once we have a specific 64-bit MSI to install on a 64-bit OS), I added a custom action to the 32-bit MSI and scheduled it in the InstallExecuteSequence and InstallUiSequence tables.  The custom action checks to see if the Windows Installer 64-bit property is set (which indicates that the MSI is being invoked on a 64-bit system), and if that is set, it will block the MSI from installing

Where to read more about 64-bit issues related to Windows Installer

When working on this example, I relied heavily on the information in this post on Heath Stewart's blog and the links to Windows Installer MSDN topics that are included in it.  If you are looking for more detailed information about how Windows Installer works behind the scenes in 64-bit scenarios, I encourage you to check out this blog post and also the other topics in Heath's 64-bit blog category.

<update date="3/23/2009"> Fixed broken link to sample download location. </update>

 

  • PingBack from http://msdnrss.thecoderblogs.com/2007/08/10/example-wix-based-setup-that-can-be-used-to-build-both-32-bit-and-64-bit-msis/

  • A cleaner way is

    <Package InstallerVersion="300" Compressed="yes"

       Platforms="$(var.Platform)"/>

    Then set for 32 bit

    -d"Platform=Intel"

    and 64 bit

    -d"Platform=x64"

    (But don't get me started on MS inconsistant naming of directories in build enviroments...

    Intel / x86 / amd64 / x64 / i386 )

  • Hi Garthy - You are right, that will work too, and it ends up looking a little cleaner in the WXS file.  This method requires setting a second pre-processor variable (Platform) when calling candle.exe.

  • Hello..I wanted to know if this will work fine with Wix 2.0. Basically when I invoke an MSI package which is built for x64(by specifying the 'Platforms' property on the package and 'Win64' properties on all components) through Octopus, the misexec process that gets invoked in the task manager is the 32 bit process (wow64mode). I wanted to know if specifying these properties on the MSI will help it decide which mode of msiexec to invoke, or do I need some additional configuration. For simplicity purposes I am just creating an only 64 bit MSI initially and will do the switching later on.

  • Hi Sameeksha - Yes, the technique in this blog post will also work if you're using WiX v2.0 instead of WiX v3.0 to create your MSI.  The general rule of thumb is that if something can be done in Windows Installer itself, there will be support for creating MSIs with WiX to do so as well.

    One thing I'd suggest taking a look at is the process that you're using to launch your MSI in this scenario.  I'm not familiar with the Octopus tool that you mentioned, but is it possible that it is a 32-bit process or it is specifically using a 32-bit version of cmd.exe when launching your MSI?

    There is a note at http://msdn2.microsoft.com/library/aa372396.aspx that indicates that you need to compile bootstrapping applications for 64-bit.  That leads me to believe that the processor architecture of the launching application ends up controlling the processor architecture of msiexec.exe that ends up getting invoked when installing an MSI.

    Hopefully this helps.

  • Thanks much for your response. However when I run the MSI by double-clicking on it, it spawns the msiexec 32 bit process. Similarly when I try installing it through Octopus the msiexec 32 bit process is invoked. I guess this means Octopus detects this as a 32 bit MSI. Following is my small Wix file as made for x64. Does anything look obviously wrong in it, or does it need any additional configuration for being a 64 bit MSI?

    <?xml version="1.0" encoding="UTF-8"?>

    <Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">

     <Product Id="{222409CD-C3F6-4344-B84B-6EA6A3105FC6}" Name="Client Center API Test" Language="1033" Version="1.0.0.0" Manufacturer="Microsoft Corporation">

       <Package Id="????????-????-????-????-????????????" Description="Client Center API Test 1.0.0.0" Comments="This will deploy the test files for ClientCenter API" InstallerVersion="200" Compressed="yes" Platforms="x64"/>

       <Property Id='SOURCEFOLDER' Value='\\cpidssbld01\Latest-AdCenter_Application_ClientCenter2_2.0\retail\i386\Test\Api' />

       <Property Id='TESTFILESTARGETFOLDER' Value='C:\CCApiTest' />

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

       <Directory Id="TARGETDIR" Name="SourceDir">

         <Directory Id="TESTFILESTARGETFOLDER" Name="trgtdir">

           <Component Id="CopyTestFilesComponent" Guid="{36F8D815-444C-4908-A1E0-A47A8F9436E0}" Win64="yes">

             <CopyFile Id="CustomerAndAccountIds.xml" SourceName="CustomerAndAccountIds.xml" SourceProperty="SOURCEFOLDER" DestinationDirectory="TESTFILESTARGETFOLDER"/>

           </Component>

         </Directory>

       </Directory>

       <Feature Id="ClientCenterApiTestFeature" Title="ClientCenterApiTestFeature" Level="1">

         <ComponentRef Id="CopyTestFilesComponent" />

       </Feature>

     </Product>

    </Wix>

    Thanks.

  • Hi Sameeksha - The WiX authoring looks like it should work to me.  Can you confirm in the resultant MSI that the summary information stream indicates that it is a 64-bit MSI (using a tool like Orca from the Windows SDK - http://msdn2.microsoft.com/library/aa370557.aspx)?  Also, if you double-click the MSI on a 32-bit OS, does it give an error or allow you to install?  If the MSI is correctly marked as a 64-bit MSI, then it should not allow you to attempt to install it on a 32-bit version of Windows.

  • Hello Aaron

    Thanks a lot for your help. The WiX that I posted above is a sample that exhibited the same behavior as my bigger MSI. The MSI that was getting built was indeed a 64-bit MSI, but the problem was that I had some Custom Actions in there, which involved vbs calls. On 64 bit mahines, the script engine gave problems if the script calls tried to be executed in 32 bit context. Apparently I needed to set the Win64 attribute on each of the Custom Actions too, apart from the Components.

    So In order to make an MSI for 64 Bit, we need

    1. Platforms attribute on Package

    2. Win64 attribute on Components

    3. Win64 attribute on Custom Actions

    An additional point. When using CoreXT in order to build the MSI, we can set the Candle pre-processor flag to the BUILDTARGET variable that is available in the context. This can be done by setting:

    USER_CANDLE_FLAGS = $(USER_CANDLE_FLAGS) -dBUILDTARGET=$(BUILDTARGET)

    in the sources file, and then using

    <Package Platforms='$(var.BUILDTARGET)' ../> in WiX.

    Thanks a million for your post, it really guided all the way through.

  • Hi Sameeksha - You're correct - if you have a custom action that specifically requires that it run as a 64-bit process, you have to mark the custom action for Win64 or else it will run in a 32-bit msiexec process, even if it is run from a 64-bit MSI.  I didn't have any such custom actions in the example in this blog post so I didn't cover that scenario well enough.  I'm glad you were able to figure this out and get things working in your system.

  • I bet it would be easier if all the components and custom actions inherited the property of the package. The Win64 attribute on the individual pieces could provide flexibility should the need be to override (which would be the case when we explicity want to execute a component/custom action in a 64-bit package to run as a 32-bit process or vice-versa).

  • Hi Aaron,

     First of all thatks for all the great work you are doing to help Wix users. I have read many of ur articles. I am not sure if i am placing my problem in correct thread.

    I am a newbie in Wix, my problem is i am trying to check for the NT OS.

    Can i set a variable using Wix which hold the Version info. Is there some thing like $(var.OSVersion)?

    Thanks in advance.

    Vivek

  • Hi VivekChandra - There is a built-in Windows Installer property named VersionNT that you can use to check the OS version.  I'd suggest checking out the documentation for this property, starting with the topic at http://msdn.microsoft.com/library/aa372495.aspx.

    Also, there is a WiX users group that is very helpful for general questions.  I'd also suggest checking that out because there are a lot of WiX experts that hang out there, plus any questions and answers that end up there are searchable so that others can find it in the future too.  You can check out http://wix.sourceforge.net/mailinglists.html#wix-users for more information about this users group.

  • This article will serve as a central repository for topics that I have written about Windows Media Center

  • Getting DVRMSToolbox Commercial Skip add-in to work under Vista 64-bit

  • Since you are making sure that the 32 bit version will not install on 64 bit machine, you are having different GUIDs for components and for the product, in essence you are having two different parallel products. Don't You need two different upgrade codes? (I am assuming that no previous version of the product has been shipped).

Page 1 of 2 (20 items) 12
Leave a Comment
  • Please add 2 and 1 and type the answer here:
  • Post