Partilhar via


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

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 https://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>

Comments

  • Anonymous
    August 09, 2007
    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/

  • Anonymous
    August 09, 2007
    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 )

  • Anonymous
    August 10, 2007
    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.

  • Anonymous
    March 25, 2008
    The comment has been removed

  • Anonymous
    March 25, 2008
    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.

  • Anonymous
    March 25, 2008
    The comment has been removed

  • Anonymous
    March 26, 2008
    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.

  • Anonymous
    March 28, 2008
    The comment has been removed

  • Anonymous
    March 28, 2008
    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.

  • Anonymous
    March 28, 2008
    The comment has been removed

  • Anonymous
    September 11, 2008
    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

  • Anonymous
    September 11, 2008
    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.

  • Anonymous
    October 22, 2008
    This article will serve as a central repository for topics that I have written about Windows Media Center

  • Anonymous
    January 11, 2009
    Getting DVRMSToolbox Commercial Skip add-in to work under Vista 64-bit

  • Anonymous
    February 05, 2011
    The comment has been removed

  • Anonymous
    February 06, 2011
    Hi Umesh - That depends on your scenario.  I modeled the example in this blog post after the .NET Framework setup.  It has separate packages for 32-bit and 64-bit OS's, and it does not allow both of them to be installed on the same computer (the 64-bit package contains all of the payload of both the 32-bit and 64-bit builds).  It has the same upgrade code for both the 32-bit and 64-bit MSIs. If you plan to allow your user to install both the 32-bit and the 64-bit MSIs on the same computer, then I think it would be best to have different upgrade codes for each MSI.

  • Anonymous
    February 08, 2011
    Hi, I am converting the setup to conditionally build for 32 or 64 bit platform. Would the following code suffice to make sure that 64 bit WIXCA is used for 64 bit platform? Thanks. Umesh Code snippet:  <?if $(var.Platform) = x64 ?>  <?define Win64 = "yes" ?>  <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>  <?define PlatformCAQuietExecDLLEntry = "CAQuietExec64"?>  <?define PlatformQtExecCmdLine = "QtExec64CmdLine"?>  <?else ?>  <?define Win64 = "no" ?>  <?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>  <?define PlatformCAQuietExecDLLEntry = "CAQuietExec"?>  <?define PlatformQtExecCmdLine = "QtExecCmdLine"?>  <?endif ?> .... .... <CustomAction Id="QtRestartMyProgramCmd" Property="QtRestartMyProgram"            Value =""[INSTALLLOCATION]MyProgram.exe""             Return="check" Execute="immediate" /> <CustomAction Id="QtRestartMyProgram" BinaryKey="WixCA"  DllEntry="$(var.PlatformCAQuietExecDLLEntry)"            Execute="deferred"  Impersonate="no"/> ..... ... Similarly writing code for immediate QuietcExec command Thanks Umesh

  • Anonymous
    February 10, 2011
    Hi Umesh - Yes, I think this type of authoring would work fine.  I would also suggest building both your 32-bit and 64-bit MSIs and double-checking the authoring in Orca to make sure it looks the way you would expect in both cases (and of course, testing the installation of both of the MSIs on their respective processor architectures).

  • Anonymous
    September 27, 2011
    The comment has been removed

  • Anonymous
    September 28, 2011
    Hi Reddy - Are you sure you marked the Platform value so you're building a 64-bit MSI in this scenario?  Do you have a verbose MSI log file from an installation scenario that you could upload to a file server (such as http://skydrive.live.com) so I could take a closer look?