If your web application product has any 32-bit dependencies that, for some reason, you are unable to shed, and if you are installing on a 64-bit Windows Server environment, you need to turn on the ‘Enable 32-Bit Applications’ setting found on the application pool. Failure to do so will typically result in a non-functioning application.

This setting is off by default, which means that it is the job of your product’s installer to turn it on. Unfortunately, this particular option is not reflected in the WiX schema in any shape or form.

I’ve seen a number of solutions on the Internet for this issue, but none of them are completely correct, and some are very wrong.

There are two ways you can turn on this option: 1. You can declare an XmlFile element, and use that to open the applicationHost.config file, find the element pertaining to your application pool, and then set enable32BitAppOnWin64 to true. 2. You can define a custom action to invoke the appcmd executable to do the same thing.

Normally, if you can ever avoid writing your own custom action, especially one that invokes an executable, you would do very well to do so. This is a philosophy I highly recommend; I can attest that it has resulted in a lot of success for me.

In this rare case, however, XmlFile can easily be the worst way to do it. Depending on your circumstances, it could also be a solid choice. Let’s go over why.

XmlFile

If you want to use a XmlFile element to set ‘Enable 32-Bit Applications’, then I would recommend putting it under its own component. That way, you can define a condition for when to execute it.

You want a condition, because you only want to perform the file modification on a 64-bit system running IIS7. Although IIS6 also can come in 64-bit, the way it handles whether 32-bit applications are allowed or not is different from IIS7 (it is a global setting, not a per-application-pool setting). Also, I have yet to encounter a customer that has a 64-bit IIS6 installation. The short end of the stick here is that you’ll need to find another way to do what we’re doing here for 64-bit IIS6 servers.

Inside the XmlFile element, we’ll be looking for the entry for our application pool. An XPath expression will be used to do so. I find the best and/or simplest filter to use here is the name of your application pool (hell, maybe that’s the only identifying element, don’t know).

The attribute we care about here is enable32BitAppOnWin64. This is going to be set to true.

The following fragment demonstrates this:

      <Component Id="Enable32BitAppPoolComponent" Guid="{21CF6C2A-90D4-4791-A0AC-55D6D1177F18}">
        <Condition><![CDATA[NOT Installed AND VersionNT64 >= 600]]></Condition>

        <util:XmlFile Id="Enable32BitAppPool"
                      Action="setValue"
                      ElementPath="//configuration/system.applicationHost/applicationPools/add[\[]@name='YourProductAppPool'[\]]/@enable32BitAppOnWin64"
                      File="[WindowsFolder]system32\inetsrv\config\applicationHost.config"
                      Value="true"
                      />
      </Component>

Very simple. And with this, you get all the benefits of using a built-in WiX extension. If something goes wrong, you’ll have full rollback support, and you’ll also have great communication in regards to what errors are occurring, if any do happen.

Big problem with this scenario. If you are trying to deploy a 32-bit web application, it would make sense then that your installer is a 32-bit installer. I’m not sure what the norms may be for everyone else, but I’m only going to package a 64-bit installer if what I’m installing is truly 64-bit.

And that’s the problem. Because you have a 32-bit installer, you cannot get access to the directory that the applicationHost.config file resides in (C:\Windows\System32\Inetsrv).

The reason why has everything to do with the file system redirection in place on 64-bit systems. 32-bit applications cannot access 64-bit only directories such as C:\Windows\System32. Instead, they will be redirected to C:\Windows\SysWOW64.

The problem for you, is that the inetsrv folder found under SysWOW64 does not contain an applicationHost.config.

Due to the reasons above, I’ll have to say that using XmlFile is the wrong way to go. If you happen to be packaging your 32-bit app in a 64-bit installer, then it will work for you, but I’d have to ask what you’re thinking packaging a 32-bit app in a 64-bit installer, frankly.

With that said, let’s look at the alternative.

Custom Action Invoking AppCmd

Weighing what we’ve learned in the previous section, it is my opinion that this is the correct way to go about our business. There are some solutions online that point to how to do this, however, I failed to find one 100% correct.

In the other solutions I’ve found online, they all tell you to make a normal custom action that runs immediately in order to call the appcmdexecutable. They also then have it scheduled to run after InstallFinalize.

That’s not how you want to go about doing this. You will run into failure if you do.

Instead, you first need to have a deferred custom action with impersonation disabled. Second, you need to schedule the custom action to run before InstallFinalize, as is the requirement with deferred custom actions.

If you don’t do this, then you’ll be attempting to execute this command with a security context that most likely lacks the permissions to do so.

The appcmd executable can be found in the C:\Windows\SysWOW64\Inetsrv directory as well as C:\Windows\System32\Inetsrv. This is unlike the applicationHost.config file we were trying to edit in the previous section.

All you do is provide the executable the name of your app pool, and the attribute you want to set along with the value.

Doing all of this, we will arrive at the correct solution to this problem, which is the following:

        <CustomAction Id="Enable32BitAppPool"
                      Return="asyncNoWait"
                      Directory="TARGETDIR"
                      ExeCommand="[SystemFolder]inetsrv\appcmd set apppool /apppool.name:&quot;YourProductAppPool&quot; /enable32BitAppOnWin64:true"
                      Impersonate="no"
                      Execute="deferred"
                      />

…for your custom action, and then inside your InstallExecuteSequence:

    <InstallExecuteSequence>
      .
      .
      <Custom Action="Enable32BitAppPool" Before="InstallFinalize"><![CDATA[NOT Installed AND VersionNT64 >= 600]]></Custom>
    </InstallExecuteSequence>

And you’re done.

Matt Weber

I'm the founder of Bad Echo LLC, which offers consulting services to clients who need an expert in C#, WPF, Outlook, and other advanced .NET related areas. I enjoy well-designed code, independent thought, and the application of rationality in general. You can reach me at matt@badecho.com.

  2 Responses to “‘Enable 32-Bit Applications’ with WiX”

  1. Hi, I had the opposite issue, I needed to set it to false, as it was automatically set to true and this link seems to suggest that setting Win64=”yes” in all app-pools did the trick. However, the issue is that I had is that I could get all the components to Win64 = “yes” because I had a large number of auto generated components by a pre-build “Heat” and turns out heat can’t auto-check the components to Win64. There is an -arch:x64 switch that was supposed to do the magic, but unfortunately it didn’t solve the Enable-32 bit app problem.

    Your first technique did not work for me as there is no choice in the order of the installation of the components and the XmlFile action was always executed before the app pool was created, so it would not find the app pool in the applicationHost.config.

    Just as a note for anyone else who gets here looking for answers

  2. Useful stuff, Thanks for sharing.

Leave a Reply to Ashish Cancel reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
   
© 2012-2013 Matt Weber. All Rights Reserved. Terms of Use.