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>

 

  • 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.

  • 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

  • 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).

  • Hi Aaron,

    I have a 64bit Quiet execution custom action similar to the example provided in above post, but when I install the 64bit MSI on 64bit operating system (Win 2008) it is executing the custom action from C:\Windows\SysWOW64\cmd.exe instead of C:\Windows\system32\cmd.exe

    I even tried invoking the executable from C:\Windows\system32\cmd.exe prompt using below code but it didn't help. Any suggestions how to make this CA run from C:\Windows\system32\cmd.exe

    <CustomAction Id="QtRestartMyProgramCmd" Property="QtRestartMyProgram"

    Value =""C:\Windows\system32\cmd.exe" /c "[INSTALLLOCATION]MyProgram.exe""

    Return="check" Execute="immediate" />

    <CustomAction Id="QtRestartMyProgram" BinaryKey="WixCA"  DllEntry="$(var.PlatformCAQuietExecDLLEntry)"

    Execute="deferred"  Impersonate="no"/>

    Thanks,

    Reddy

  • 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?

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