Add-in for 64 and 32 bit Office

My NoReplyAll add-in, which I've talked about before, uses absolutely nothing that ties it to 32 or 64 bit Outlook - it's all "anycpu" with no architecture specific dependencies. However, the latest installer is 32 bit, with the result that the add-in won't appear in 64 bit Outlook.

This wasn't a problem with a ClickOnce installer but, for reasons explained elsewhere, I wanted to make a MSI based install package, and MSI technology is bit-width specific. One approach is to create both 32 and 64 bit packages, and have a bootstrapper to choose which to run but I want to avoid that because the content of the two packages would be identical, apart from the flags saying whether they were 64 bit or not. It's also totally the wrong thing for another reason: the MSI bitness declares what flavour of the operating system the package is intended for, and says nothing about the bitness of Office. People run 32 bit Office on 64 bit Windows (I do, for example), so I'd really want a 32 bit installer for this setup, not the 64 bit one.

Let's take a brief step back: what does it mean for the installer to be 64 or 32 bit? Pretty much all that happens is when a 64 bit installer runs on a 64 bit OS, or when a 32 bit one runs on a 32 bit OS, the program files directory maps to (typically) "C:\Program Files" and the registry keys such as HKLM\Software\Microsoft map, not too surprisingly, on to HKLM\Software\Microsoft. However, if you run a 32 bit MSI on a 64 bit OS, program files is mapped to "C:\Program Files (x86) " and that registry key will be sent to HKLM\Software\Wow6432Node\ Microsoft - this all happens automatically via "registry reflection." I'm sure there are a few other differences too, but they're not important here. What's more, there's no way (within Windows Installer technology), as far as I'm aware, for a 32 bit MSI package to reach out to the non-redirected parts of the filing system or registry without writing extra code. (For completeness, there's no similar mapping when running a 64 bit installer on a 32 bit OS - primarily because you just can't install 64 bit MSIs on 32 bit Windows!)

Now, the directory in which I place the add-in bits is irrelevant, but the registry is significant... By releasing a 32 bit installer, I was placing the registry stuff under HKLM\Software\Wow6432Node\Microsoft\Office\Outlook on a 64 bit version of Windows - and this so happens to be where 32 bit Outlook looks for its add-ins. People running 64 bit Office would see no add-in because it's looking under HKLM\Software\Microsoft\Office\Outlook. (And the reason that there's no problem with ClickOnce is that it adds the registry settings under HKCU, which doesn't have this redirection and is visible to both 32 and 64 bit Outlook.)

I did consider looking to see what bitness of Office is installed and trying to modify the appropriate part of the registry, but decided against that because I wouldn't want the add-in to "vanish" were someone to uninstall their 32 bit Outlook and then install 64 bit (or vice versa). Instead, I decided that I would always install in the 32 bit friendly location but, on 64 bit Windows, also copy the registry settings "up" as part of the install process. Now, 32 bit applications can't (easily) see the 64 bit parts of the registry because of the automatic redirection, but 64 bit executables get to see everything, so I considered writing a small executable which would run post-install to copy the contents of the appropriate registry key, and also delete it on uninstall. However, then I stumbled across the REG command - which does allow access to the whole registry without me having to write anything more than a command line! In particular, it can copy the contents of one registry key to another, so I can let Windows Installer deal with the 32 bit part of the registry (in a 32 bit installer) as normal, and then use REG to copy what was placed there into the equivalent 64 bit location.

I made the following additions to the WiX Product.wxs file:

     <Property Id="CopyReg64Key" Value='"REG.EXE" COPY "HKLM\Software\WoW6432Node\Microsoft\Office\Outlook\Addins\NoReplyAll" "HKLM\Software\Microsoft\Office\Outlook\Addins\NoReplyAll" /s /f /reg:64' />
    <CustomAction Id="CopyReg64Key" Execute="deferred" Return="ignore" Impersonate="no" BinaryKey="WixCA" DllEntry="CAQuietExec" />

    <Property Id="DeleteReg64Key" Value='"REG.EXE" DELETE "HKLM\Software\Microsoft\Office\Outlook\Addins\NoReplyAll" /f /reg:64' />
    <CustomAction Id="DeleteReg64Key" Execute="deferred" Return="ignore" Impersonate="no" BinaryKey="WixCA" DllEntry="CAQuietExec" />
     <InstallExecuteSequence>
      <Custom Action="CopyReg64Key" Before="InstallFinalize">
        <![CDATA[$CMP_VstoManifest=3]]>
      </Custom>
      <Custom Action="DeleteReg64Key" Before="RemoveFiles">
        <![CDATA[$CMP_VstoManifest=2]]>
      </Custom>
    </InstallExecuteSequence>

The first pair of lines defines a custom action which copies the 32 bit registry entries to the "same place" in the 64 bit part. This will fail silently on a 32 bit operating system, which is fine. Unfortunately it will also fail on Windows XP, since the reg.exe that that comes with doesn't recognise the /reg:64 command line option, but I don't expect that to affect very many people. This is using the WiX quiet execution extension, which lets me invoke a command line without showing a console window - the simpler custom action shown below would cause a brief console flash when it executes:

 <CustomAction Id="CopyReg64Key" Execute="deferred" Return="ignore" Impersonate="no" Directory="INSTALLFOLDER"
              ExeCommand='REG COPY "HKLM\Software\WoW6432Node\Microsoft\Office\Outlook\Addins\NoReplyAll" "HKLM\Software\Microsoft\Office\Outlook\Addins\NoReplyAll" /s /f /reg:64' />

The next pair of lines deletes the extra registry setting. On a 32 bit OS, this would delete the same values as the "normal" registry manipulation, so that's OK too. And the final bunch of lines cause the first custom action to be executed near the end of the install sequence and uninstall sequence as appropriate.

With all this in place, the bulk of the installer runs as before, updating the 32 bit parts of the registry. After all that, the custom actions fiddle with the 64 bit part of the registry, and we're done.

Look out for this in the next version of the add-in to be published...