How do you package a VSTO Word addin for deployment (to Office 32 bit) using WIX?

Update (11/26/2019): If your setup uses 64-bit Office, see How do you package a VSTO Word addin for deployment to a 64-bit Windows 10 machine running Microsoft Office 64 bit using WIX?

Successfully packaged and deployed my add-in using the WiX tool set

Credit: I learned most of this using Pieter van der Westhuizen's example on the Add-in Express Blog.

I used Visual Studio Pro 2017, .NET 4.6.1, and C# on my development machine (64-bit) to implement my VSTO Word add-in.

My requirement is to deploy the add-in once to a 64-bit production machine (i.e., a Citrix virtual desktop master image) so it's available to any user who logs onto the production machine (i.e., logs on to a virtual desktop based on the master image). The 32-bit version of Word 2013 is installed on the master image.

As I understand it, this means the 'add-in' has to be installed under 'C:\Program Files (x86)' for two reasons:

  1. So all users have access to the add-in, and
  2. Under (x86) because it's the 32-bit version of Word).

Also, because all users need to access the add-in, the required VSTO registry key settings go under the root HKLM (and not HKCU). Essentially, this 'all users' setup is the opposite of the 'one user' Click-Once setup. Apropos of nothing, I'm in an enclave that is not connected to the Internet. So, all software I use is downloaded elsewhere, and then carried into the enclave and installed locally.

The release files for my VSTO word add-in (i.e, in C:\....\Visual Studio 2017\Projects\FooAddIn\FooAddIn\bin\Release) are:

  • FooAddIn.dll
  • FooAddIn.dll.manifest
  • FooAddIn.vsto
  • Microsoft.Office.Tools.Common.v4.0.Utilities.dll

What I did

  • Downloaded and installed 'WiX' v3.11.1 onto my development machine from http://wixtoolset.org/releases/.

  • Downloaded and installed 'Wix Toolset Visual Studio 2017 Extension' onto my development machine from https://marketplace.visualstudio.com/items?itemName=RobMensching.WixToolsetVisualStudio2017Extension

  • Opened my add-in project FooAddIn using VS 2017 and in Solution Explorer, right-mouse clicked on the top-line Solution node and clicked Add -> New Project.

  • In the Add New Project dialog, clicked on v3 under WiX Toolset and then clicked on Setup Project for WiX v3. I named the new project FooAddInSetup. Visual Studio Solution Explorer shows Solution FooAddIn (2 projects), project FooAddIn, and project FooAddInSetup.

  • Under FooAddInSetup -> References, added references to C:\Program Files (x86)\WiX Toolset v3.11\bin\WixNetFxExtension.dll and C:\Program Files (x86)\WiX Toolset v3.11\bin\WixUIExtension.dll (These are needed by elements of the Product.wxs file to build the installer).

  • Configured VS to also build the setup program: In VS, click on Build -> Configuration Manager. In the Configuration Manager dialog, checked the Build check box for FooAddInSetup.

  • Created EULA.rtf (mine says "This is license-free software") and placed it in C:....\Visual Studio 2017\Projects\FooAddIn\FooAddInSetup

  • Created a preprocessor variable for the path to the location of my VSTO release files: In Solution Explorer, right mouse clicked FooAddInSetup -> Properties. On the FooAddInSetup tab, Clicked on 'Build'. In the General section, clicked Define 'Debug' preprocessor variable. In the Define preprocessor variables: textbox, entered AddinFiles=..\FooAddIn\bin\$(Configuration)\

  • Populated the boilerplate WiX Product.wxs file for my add-in as shown below under Product.wxs file

  • Note: In the wxs file, I modified the Visual Studio 2010 Tools for Office Runtime hyperlink in the Condition element - the one in Pieter's example is dead.

  • I set the Solution Configuration to Release and built the solution.

  • Copied FooAddInSetup.msi from ...\FooAddInSetup\bin\release on my dev machine to my production machine (the VDI master) and ran the setup program as admin.

Results

  1. Without regard to the registry settings I asserted in the wxs file, my registry keys were created in HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Office\Word\AddIns\LesCaveatAddIn, i.e., they went into HKLM as expected, but they went into \Software\Wow6432Node\Microsoft..... instead of \Software\Microsoft.... as I coded in the wxs file. I assume this is because my production machine is a 64-bit machine.

  2. As expected, the add-in itself was installed under c:\program files (x86)

  3. Brought up Word, and the add-in was loaded as expected

Product.wxs file

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">

  <!--
  The boilerplate Product.wxs file already contains the minimum amount of elements needed to build a WiX installer. 
  If the Product element, Id attribute is set to an asterisk (*), WiX will generate a new GUID every time the setup project is compiled (I left it as-is). 
  Change the Name attribute value and Manufacturer attribute value to values of your choice.
  -->
  <Product Id="*"
           Name="FOO Add-In"
           Language="1033"
           Version="1.0.0.0"
           Manufacturer="Foo Masters"
           UpgradeCode="4b35cc09-4780-4644-a7d4-f5901f7a7e45">

    <!--Attributes shown are the minimum number needed to build the setup project.-->
    <Package InstallerVersion="200"
             Compressed="yes"
             InstallScope="perMachine" />

    <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />

    <!-- Verify if VSTO Office Runtime is installed -->
    <Property Id="VSTORUNTIMEREDIST">
      <RegistrySearch
        Id="VSTORuntimeRedist"
        Root="HKLM"
        Key="SOFTWARE\Microsoft\VSTO Runtime Setup\v4R"
        Name="Version"
        Type="raw" />
    </Property>

    <Condition
      Message="The Visual Studio 2010 Tools for Office Runtime is not installed. 
  Please download and install from https://www.microsoft.com/en-us/download/details.aspx?id=48217.">
      <![CDATA[Installed OR VSTORUNTIMEREDIST>="10.0.30319"]]>
    </Condition>

    <!-- Verify if .NET Framework is installed -->
    <PropertyRef Id="NETFRAMEWORK40FULL"/>
    <Condition Message="This application requires .NET Framework 4.0.">
      <![CDATA[Installed OR NETFRAMEWORK40FULL]]>
    </Condition>

    <!--I want one Cab file, so only one Media element is needed. Make sure the EmbedCab attribute value is "yes".-->
    <Media Id="1" Cabinet="FooAddin.cab" EmbedCab="yes"/>

    <!--Set values for display on setup progeam UI-->
    <Feature Id="ProductFeature" Title="FOO Add-In" Level="1">
      <ComponentGroupRef Id="ProductComponents" />
      <ComponentRef Id="Registry_FriendlyName" />
      <ComponentRef Id="Registry_Description" />
      <ComponentRef Id="Registry_Manifest" />
      <ComponentRef Id="Registry_LoadBehavior" />
    </Feature>

    <!--Specify that the WiXUI_Minimal UI should be used, i.e, the simplest UI available -->
    <UIRef Id="WixUI_Minimal" />

    <!--Specify the EULA file to use-->
    <WixVariable Id="WixUILicenseRtf" Value="EULA.rtf" />

  </Product>

  <Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLFOLDER" Name="FooAddin" />

        <!-- Add required VSTO registry entries for 32-bit Word -->
        <!-- see https://learn.microsoft.com/en-us/visualstudio/vsto/registry-entries-for-vsto-add-ins?view=vs-2019-->

        <Component Id="Registry_FriendlyName">
          <RegistryValue Id="RegKey_FriendlyName" Root="HKLM"
                         Key="Software\Microsoft\Office\Word\AddIns\FooAddin"
                         Name="FriendlyName"
                         Value="FOO Add-In"
                         Type="string" KeyPath="yes" />
        </Component>
        <Component Id="Registry_Description">
          <RegistryValue Id="RegKey_Description" Root="HKLM"
                         Key="Software\Microsoft\Office\Word\AddIns\FooAddin"
                         Name="Description"
                         Value="FOO Add-In"
                         Type="string" KeyPath="yes" />
        </Component>
        <Component Id="Registry_Manifest">
          <RegistryValue Id="RegKey_Manifest" Root="HKLM"
                         Key="Software\Microsoft\Office\Word\AddIns\FooAddin"
                         Name="Manifest" Value="[INSTALLFOLDER]FooAddin.vsto|vstolocal"
                         Type="string" KeyPath="yes" />
        </Component>
        <Component Id="Registry_LoadBehavior">
          <RegistryValue Id="RegKey_LoadBehavior" Root="HKLM"
                         Key="Software\Microsoft\Office\Word\AddIns\FooAddin"
                         Name="LoadBehavior" Value="3"
                         Type="integer" KeyPath="yes" />
        </Component>

      </Directory>
    </Directory>
  </Fragment>

  <Fragment>

    <!-- Add refs to the components of the VSTO-->

    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">

      <Component Id="MSOfficeToolsCommon_dll_Component">
        <File Id="MSOfficeToolsCommon_dll" KeyPath="yes"
          Name="Microsoft.Office.Tools.Common.v4.0.Utilities.dll"
          Source="$(var.AddinFiles)"></File>
      </Component>

      <Component Id="FooAddin_dll_Component" >
        <File Id="FooAddin_dll" KeyPath="yes"
              Name="FooAddin.dll"
              Source="$(var.AddinFiles)" />
      </Component>

      <Component Id="FooAddin_vsto_Component">
        <File Id="FooAddin_vsto" KeyPath="yes"
          Name="FooAddin.vsto"
          Source="$(var.AddinFiles)"></File>
      </Component>

      <Component Id="FooAddin_dll_manifest_Component">
        <File Id="FooAddin_dll_manifest" KeyPath="yes"
          Name="FooAddin.dll.manifest"
          Source="$(var.AddinFiles)"></File>
      </Component>

    </ComponentGroup>
  </Fragment>
</Wix>

I usually use the Click-Once deployment within Visual Studio. You can deploy it to a network path so other users will be able to install it.

First you want to create a non-expiring certificate for Visual Studio projects

Type Developer Command in the Start Menu search and right click and select Run as administrator

Start Menu

Paste the following commands in the command prompt for MakeCert and pvk2pfx

MakeCert /n "CN=Your New Cert" /r /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /e "01/01/2100" /sv MyNewCert.pvk MyNewCert.cer 
pvk2pfx -pvk MyNewCert.pvk -spc MyNewCert.cer -pfx MyNewCert.pfx

Note:

  • The date format is the US standard MM/DD/YYYY
  • The -f parameter can be used at the end of the pvk2pfx line for overwriting an existing file
  • You'll get prompted to create a password (this is optional)

cmd prompt

After the password prompt, you'll need to run the second command line by just pressing the Enter key.

cmd prompt2

Now you can select the same certificate for multiple Visual Studio projects

In the Visual Studio project properties, select Signing* click on Select from File…. Navigate to the same path from the command prompt and select the certificate file (*.pfx)

Visual Studio Signing

Publish the project

Then go to the Publish tab in the project properties and click Publish Now. It will create a executable file in the published location. Then you just need to send a link to the .exe file to your end-users.

publish