Logo
HOWTO: Create a setup for a Visual Studio add-in for the current user (not requiring admin rights) using Windows Installer XML (WiX)

Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Visual Studio 2005
Date: August 2011   Microsoft Visual Studio 2008
      Microsoft Visual Studio 2010
       
Introduction

This article explains how to create a setup for a Visual Studio add-in for all users (requiring administrator privileges), not just for the current user, using Windows Installer XML (WiX), a toolset that builds Windows installation packages (MSI) from XML source code.

The WiX toolset provides command-line tools to generate the MSI setups, but integration within Visual Studio projects is also provided through Votive (a Visual Studio package for WiX that lets you create and build WiX setup projects using the Visual Studio IDE). This article assumes that you are somewhat familiar with MSI and WiX.

More Information

The provided setup assumes an add-in that creates commands, buttons and commandbars using a temporary user interface (see the article HOWTO: Adding buttons, commandbars and toolbars to Visual Studio .NET from an add-in), not a permanent user interface (specifically, it does not use permanent commandbars). Some considerations about the setup are the following:

  • Since the add-in is installed for the current user without administrator rights (InstallScope="perUser" in the sample):
    • It is installed in the following folder only available to the current user:
      • Windows XP: "C:\Documents and Settings\<username>\Application Data"
      • Windows Vista / Windows 7: "C:\Users\<username>\AppData\Roaming"
    • It creates the links to the help file, to a web site and to the unsinstaller in the Start menu, Programs for the current user.
    • It uses XML registration through an .AddIn file that will be placed in the following folders making the add-in available only to the current user (see the article INFO: Default .AddIn file locations for Visual Studio add-ins):
      • Windows XP:
        • Visual Studio 2005: "C:\Documents and Settings\<username>\Application Data\Microsoft\VisualStudio\8.0\AddIns"
        • Visual Studio 2008: "C:\Documents and Settings\<username>\Application Data\Microsoft\VisualStudio\9.0\AddIns"
        • Visual Studio 2010: "C:\Documents and Settings\<username>\Application Data\Microsoft\VisualStudio\10.0\AddIns"
      • Windows Vista / Windows 7:
        • Visual Studio 2005: "C:\Users\<username>\AppData\Roaming\Microsoft\VisualStudio\8.0\AddIns"
        • Visual Studio 2008: "C:\Users\<username>\AppData\Roaming\Microsoft\VisualStudio\9.0\AddIns"
        • Visual Studio 2010: "C:\Users\<username>\AppData\Roaming\Microsoft\VisualStudio\10.0\AddIns"
  • The add-in targets each Visual Studio version with a different DLL ("MyAddInVS2005.dll", "MyAddInVS2008.dll" and "MyAddInVS2010.dll" in the sample), although you can use a single DLL (see the article HOWTO: Create an add-in that targets several Visual Studio versions with the same add-in DLL using C# or VB.NET.)
  • The setup doesn't install a satellite DLL, but you can add it easily.
  • The setup will prompt which Visual Studio versions of the add-in will be installed.
  • A custom action will be used on uninstalling to remove the commands of the add-in, creating an instance of EnvDTE.DTE, iteraring its commands and deleting the ones that belong to the add-in (see the article HOWTO: Removing commands and UI elements during Visual Studio .NET add-in uninstallation).
  • The add-in uses a help file ("MyAddIn.chm" in the sample) and a license agreement file ("LicenseAgreement.rtf" in the sample), although you can change the script file to remove them.
  • The setup checks that Visual Studio is installed (Visual Studio Express editions don't qualify since they don't support add-ins).

The steps to create a setup for such add-in using WiX are the following:

  • Download and install the WiX toolset from http://wix.codeplex.com/. The current version at the time of this writing is 3.5, which supports Visual Studio 2005, 2008 and 2010.
  • Click the File, New Project menu, select the Windows Installer XML project type and the Setup Project template. Give the project a name and click OK.
  • Save the project.
  • Add references to the WixUIExtension.dll and WixUtilExtension.dll files.
  • In the Properties window of the project, "Installer" section, set the desired output name for the setup.
  • In the Properties window of the project, "Tool Settings" section, "Suppress specific ICE validation" textbox, add the values ICE64;ICE91.
  • Create a file named MyAddIn.AddIn in the same folder of the project with the following content:
Language: XML   Copy Code Copy Code (IE only)
<?xml version="1.0" standalone="no"?>
<Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility">
   <HostApplication>
      <Name>Microsoft Visual Studio</Name>
      <Version>ReplacedAtInstallTime</Version>
   </HostApplication>
   <Addin>
    <FriendlyName>MyAddIn</FriendlyName>
    <Description>MyAddIn</Description>
    <Assembly>ReplacedAtInstallTime</Assembly>
    <FullClassName>ReplacedAtInstallTime</FullClassName>
    <LoadBehavior>1</LoadBehavior>
    <CommandPreload>0</CommandPreload>
    <CommandLineSafe>1</CommandLineSafe>
  </Addin>
</Extensibility>
  • Put the files "MyAddInVS2005.dll", "MyAddInVS2008.dll", "MyAddInVS2010.dll", "MyAddIn.chm" and "LicenseAgreement.rtf" in the same folder of the project.
  • Replace the content of the Product.wxs file by this one (do not forget to change all GUIDs):
Language: XML   Copy Code Copy Code (IE only)
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

   <!--
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    BEGIN CUSTOMIZATION SECTION: Customize these constants
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   -->

   <!-- Ensure that you use YOUR OWN IDs; DO NOT REUSE THESE ONES -->
   <?define PRODUCT_ID  = "21BC969C-0A96-4c55-9F50-97A31FC4F89B" ?>
   <?define UPGRADE_CODE = "C530CAB2-D1E0-4441-9FBA-FF1A11163145" ?>
   <?define LICENSE_AGREEMENT_FILE_COMPONENT_GUID = "7FE08E6A-A176-41c5-AD21-589BB0BE9D21" ?>
   <?define HELP_FILE_COMPONENT_GUID = "39B521B0-9A3A-4b40-A250-C5D4692AB275" ?>
   <?define HELP_FILE_SHORTCUT_COMPONENT_GUID = "47DE74EB-8AFA-41b3-ABFC-FC0C06E4576A" ?>
   <?define VS2005_DLL_FILE_COMPONENT_GUID = "0493B874-400A-4cc8-951A-926DBDD7BADE" ?>
   <?define VS2008_DLL_FILE_COMPONENT_GUID = "72074C65-A89D-4f7b-A306-F965367D4FD9" ?>
   <?define VS2010_DLL_FILE_COMPONENT_GUID = "0A230C89-6CF8-48d1-8A0E-F6E8839A5BA5" ?>
   <?define VS2005_ADDIN_FILE_COMPONENT_GUID = "C09A42B9-7B3C-484f-92ED-D0AAB0A68E54" ?>
   <?define VS2008_ADDIN_FILE_COMPONENT_GUID = "D8C179D5-F8C7-4487-A189-5357E7D42B9B" ?>
   <?define VS2010_ADDIN_FILE_COMPONENT_GUID = "D5057F72-B845-4637-B832-6287631E6F07" ?>

   <?define APP_NAME = "My Add-In" ?>
   <?define APP_VERSION = "1.0.0.0" ?>
   <?define DEFAULT_GROUP_NAME = "My Add-In" ?>
   <?define HELP_SHORTCUT = "My Add-In Help File" ?>
 
   <?define DEST_SUB_DIR = "MyAddIn" ?>
   <?define HELP_FILE_NAME = "MyAddIn.chm" ?>
   <?define LICENSE_AGREEMENT_FILE_NAME = "LicenseAgreement.rtf" ?>
   <?define DLL_FILE_NAME_VS2005 = "MyAddInVS2005.dll" ?>
   <?define DLL_FILE_NAME_VS2008 = "MyAddInVS2008.dll" ?>
   <?define DLL_FILE_NAME_VS2010 = "MyAddInVS2010.dll" ?>
   <?define ADDIN_XML_FILE_NAME = "MyAddIn.AddIn" ?>
   <?define MY_COMPANY_NAME = "My Company" ?>
   <?define MY_COMPANY_WEB_SITE = "http://www.mycompany.com" ?>

   <!-- Ensure that these values are used for the Connect class -->
   <?define CONNECT_CLASS_FULL_NAME_VS_2005 = "MyAddInVS2005.Connect" ?>
   <?define CONNECT_CLASS_FULL_NAME_VS_2008 = "MyAddInVS2008.Connect" ?>
   <?define CONNECT_CLASS_FULL_NAME_VS_2010 = "MyAddInVS2010.Connect" ?>

   <!--
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    END CUSTOMIZATION SECTION
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   -->

   <Product Id="$(var.PRODUCT_ID)"
            Name="$(var.APP_NAME)"
            Language="1033"
            Codepage="1252"
            Version="$(var.APP_VERSION)"
            Manufacturer="$(var.MY_COMPANY_NAME)"
            UpgradeCode="$(var.UPGRADE_CODE)">

      <!-- Define the package indicating that the installation is for "Just me", not "All users" -->
      <Package InstallScope="perUser" InstallerVersion="200" Compressed="yes" />

      <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

      <!-- Properties to get the installation folders of Visual Studio 2005, 2008 or 2010.
           If the values can't be retrieved the properties will remain unset (with the FALSE value) and can be used 
           in boolean expressions later.
           The properties must be secure in order to the Repair, Change and Remove buttons of the maintenance mode to work correctly.
      -->
      <Property Id="VS2005INSTALLATIONFOLDER" Secure="yes">
         <RegistrySearch Id="VS2005InstallationFolderRegistrySearchId" Type="raw"
                         Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\8.0" Name="InstallDir"></RegistrySearch>
      </Property>
      <Property Id="VS2008INSTALLATIONFOLDER" Secure="yes">
         <RegistrySearch Id="VS2008InstallationFolderRegistrySearchId" Type="raw"
                         Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\9.0" Name="InstallDir"></RegistrySearch>
      </Property>
      <Property Id="VS2010INSTALLATIONFOLDER" Secure="yes">
         <RegistrySearch Id="VS2010InstallationFolderRegistrySearchId" Type="raw"
                         Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\10.0" Name="InstallDir"></RegistrySearch>
      </Property>

      <!-- Launch condition: check that some Visual Studio version is present when the installing.
           The OR'ed Installed variable ensures that the condition is always true when uninstalling, because we don't
           need to check that Visual Studio is present when uninstalling.
      -->
      <Condition Message="This add-in requires Visual Studio 2005, 2008 or 2010.">
         Installed OR VS2005INSTALLATIONFOLDER OR VS2008INSTALLATIONFOLDER OR VS2010INSTALLATIONFOLDER
      </Condition>
      
      <Directory Id="TARGETDIR" Name="SourceDir">

         <!-- Install the files in a subfolder of the AppDataFolder folder (CSIDL_APPDATA) -->
         <Directory Id="AppDataFolder">
            
            <Directory Id="INSTALLLOCATION" Name="$(var.DEST_SUB_DIR)">

               <!-- Install the license agreement -->
               <Component Id="LicenseAgreementFileComponentId" Guid="$(var.LICENSE_AGREEMENT_FILE_COMPONENT_GUID)">

                  <File Id="LicenseAgreementFileId" Name="$(var.LICENSE_AGREEMENT_FILE_NAME)" Vital="yes" DiskId="1" 
                        Source="$(var.LICENSE_AGREEMENT_FILE_NAME)" />
                  
                  <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                  ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                  -->
                  <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\LicenseFile" Name="Installed" 
                                 Type="integer" Value="1" KeyPath="yes"/>
                  
                  <!-- Ensure that the folder is removed when uninstalling -->
                  <RemoveFolder Id="INSTALLLOCATION" On="uninstall"/>
                  
               </Component>
               
               <!-- Install the help file -->
               <Component Id="HelpFileComponentId" Guid="$(var.HELP_FILE_COMPONENT_GUID)">

                  <File Id="HelpFileId" Name="$(var.HELP_FILE_NAME)" Vital="yes" DiskId="1" Source="$(var.HELP_FILE_NAME)" />

                  <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                  ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                  -->
                  <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\HelpFile" Name="Installed" Type="integer" 
                                 Value="1" KeyPath="yes"/>
               
               </Component>

               <!-- Install the dll file of the add-in for Visual Studio 2005 -->
               <Component Id="VS2005DllFileComponentId" Guid="$(var.VS2005_DLL_FILE_COMPONENT_GUID)">

                  <File Id="VS2005DllFileId" Name="$(var.DLL_FILE_NAME_VS2005)" Vital="yes" DiskId="1" Source="$(var.DLL_FILE_NAME_VS2005)" />

                  <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                  ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                  -->
                  <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\VS2005DllFile" Name="Installed" Type="integer" 
                                 Value="1" KeyPath="yes"/>

               </Component>

               <!-- Install the dll file of the add-in for Visual Studio 2008 -->
               <Component Id="VS2008DllFileComponentId" Guid="$(var.VS2008_DLL_FILE_COMPONENT_GUID)">

                  <File Id="VS2008DllFileId" Name="$(var.DLL_FILE_NAME_VS2008)" Vital="yes" DiskId="1" Source="$(var.DLL_FILE_NAME_VS2008)" />
               
                  <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                  ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                  -->
                  <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\VS2008DllFile" Name="Installed" Type="integer" 
                                 Value="1" KeyPath="yes"/>

               </Component>

               <!-- Install the dll file of the add-in for Visual Studio 2010 -->
               <Component Id="VS2010DllFileComponentId" Guid="$(var.VS2010_DLL_FILE_COMPONENT_GUID)">

                  <File Id="VS2010DllFileId" Name="$(var.DLL_FILE_NAME_VS2010)" Vital="yes" DiskId="1" Source="$(var.DLL_FILE_NAME_VS2010)" />
               
                  <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                  ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                  -->
                  <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\VS2010DllFile" Name="Installed" Type="integer" 
                                 Value="1" KeyPath="yes"/>

               </Component>
               
            </Directory>

            <!-- Install the .AddIn XML files in folders where Visual Studio can find them:   
              - Windows XP: "C:\Documents and Settings\<username>\Application Data\Microsoft\VisualStudio\8.0\AddIns"
                (9.0 for VS 2008, 10.0 for VS 2010)
              - Windows Vista / Windows 7: "C:\Users\<username>\AppData\Roaming\Microsoft\VisualStudio\8.0\AddIns"
                (9.0 for VS 2008, 10.0 for VS 2010)
              
              See: "INFO: Default .AddIn file locations for Visual Studio add-ins"
                   http://www.mztools.com/articles/2008/MZ2008001.aspx
            -->
            <Directory Id="MicrosoftDirId" Name="Microsoft">

               <Directory Id="VisualStudioDirId" Name="VisualStudio">

                  <Directory Id="Dir80Id" Name="8.0">

                     <Directory Id="Dir80AddInsId" Name="AddIns">

                        <Component Id="VS2005AddInFileComponentId" Guid="$(var.VS2005_ADDIN_FILE_COMPONENT_GUID)">

                           <!-- Copy the .AddIn file to the folder -->
                           <File Id="VS2005AddInFileId" Name="$(var.ADDIN_XML_FILE_NAME)" Vital="yes" DiskId="1"
                                 Source="$(var.ADDIN_XML_FILE_NAME)" />

                           <!-- Modify the Version XML element inside the .AddIn file whose Id is VS2005AddInFileId
                                to set the value "8.0" (which is the version of VS 2005) -->
                           <util:XmlFile Id="VS2005SetVersionElement" Action="setValue" File="[#VS2005AddInFileId]"
                                         ElementPath="/Extensibility/HostApplication/Version" Value="8.0" Sequence="1" />

                           <!-- Modify the Assembly XML element inside the .AddIn file whose Id is VS2005AddInFileId
                                to set value of the file whose Id is VS2005DllFileId -->
                           <util:XmlFile Id="VS2005SetAssemblyElement" Action="setValue" File="[#VS2005AddInFileId]"
                                         ElementPath="/Extensibility/Addin/Assembly" Value="[#VS2005DllFileId]" Sequence="1" />

                           <!-- Modify the FullClassName XML element inside the .AddIn file whose Id is VS2005AddInFileId
                                to set value of the variable CONNECT_CLASS_FULL_NAME_VS_2005 -->
                           <util:XmlFile Id="VS2005SetFullClassNameElement" Action="setValue" File="[#VS2005AddInFileId]"
                                         ElementPath="/Extensibility/Addin/FullClassName"
                                         Value="$(var.CONNECT_CLASS_FULL_NAME_VS_2005)" Sequence="1" />

                           <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                                ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                           -->
                           <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\VS2005AddInFile" Name="Installed" 
                                          Type="integer" Value="1" KeyPath="yes"/>

                        </Component>

                     </Directory>

                  </Directory>

                  <Directory Id="Dir90Id" Name="9.0">

                     <Directory Id="Dir90AddInsId" Name="AddIns">

                        <Component Id="VS2008AddInFileComponentId" Guid="$(var.VS2008_ADDIN_FILE_COMPONENT_GUID)">

                           <!-- Copy the .AddIn file to the folder -->
                           <File Id="VS2008AddInFileId" Name="$(var.ADDIN_XML_FILE_NAME)" Vital="yes" DiskId="1"
                                 Source="$(var.ADDIN_XML_FILE_NAME)" />

                           <!-- Modify the Version XML element inside the .AddIn file whose Id is VS2008AddInFileId
                                to set the value "9.0" (which is the version of VS 2008) -->
                           <util:XmlFile Id="VS2008SetVersionElement" Action="setValue" File="[#VS2008AddInFileId]"
                                         ElementPath="/Extensibility/HostApplication/Version" Value="9.0" Sequence="1" />

                           <!-- Modify the Assembly XML element inside the .AddIn file whose Id is VS2008AddInFileId
                                to set value of the file whose Id is VS2008DllFileId -->
                           <util:XmlFile Id="VS2008SetAssemblyElement" Action="setValue" File="[#VS2008AddInFileId]"
                                         ElementPath="/Extensibility/Addin/Assembly" Value="[#VS2008DllFileId]" Sequence="1" />

                           <!-- Modify the FullClassName XML element inside the .AddIn file whose Id is VS2008AddInFileId
                                to set value of the variable CONNECT_CLASS_FULL_NAME_VS_2008 -->
                           <util:XmlFile Id="VS2008SetFullClassNameElement" Action="setValue" File="[#VS2008AddInFileId]"
                                         ElementPath="/Extensibility/Addin/FullClassName"
                                         Value="$(var.CONNECT_CLASS_FULL_NAME_VS_2008)" Sequence="1" />

                           <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                                ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                           -->
                           <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\VS2008AddInFile" Name="Installed" 
                                          Type="integer" Value="1" KeyPath="yes"/>

                        </Component>

                     </Directory>

                  </Directory>

                  <Directory Id="Dir100Id" Name="10.0">

                     <Directory Id="Dir100AddInsId" Name="AddIns">

                        <Component Id="VS2010AddInFileComponentId" Guid="$(var.VS2010_ADDIN_FILE_COMPONENT_GUID)">

                           <!-- Copy the .AddIn file to the folder -->
                           <File Id="VS2010AddInFileId" Name="$(var.ADDIN_XML_FILE_NAME)" Vital="yes" DiskId="1"
                                 Source="$(var.ADDIN_XML_FILE_NAME)" />

                           <!-- Modify the Version XML element inside the .AddIn file whose Id is VS2010AddInFileId
                                to set the value "10.0" (which is the version of VS 2010) -->
                           <util:XmlFile Id="VS2010SetVersionElement" Action="setValue" File="[#VS2010AddInFileId]"
                                         ElementPath="/Extensibility/HostApplication/Version" Value="10.0" Sequence="1" />

                           <!-- Modify the Assembly XML element inside the .AddIn file whose Id is VS2010AddInFileId
                                to set value of the file whose Id is VS2010DllFileId -->
                           <util:XmlFile Id="VS2010SetAssemblyElement" Action="setValue" File="[#VS2010AddInFileId]"
                                         ElementPath="/Extensibility/Addin/Assembly" Value="[#VS2010DllFileId]" Sequence="1" />

                           <!-- Modify the FullClassName XML element inside the .AddIn file whose Id is VS2010AddInFileId
                                to set value of the variable CONNECT_CLASS_FULL_NAME_VS_2010 -->
                           <util:XmlFile Id="VS2010SetFullClassNameElement" Action="setValue" File="[#VS2010AddInFileId]"
                                         ElementPath="/Extensibility/Addin/FullClassName"
                                         Value="$(var.CONNECT_CLASS_FULL_NAME_VS_2010)" Sequence="1" />

                           <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                                ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as its KeyPath not a file.
                           -->
                           <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\VS2010AddInFile" Name="Installed" 
                                          Type="integer" Value="1" KeyPath="yes"/>

                        </Component>

                     </Directory>

                  </Directory>

               </Directory>

            </Directory>

         </Directory>

         <!-- Install the shortcuts to the help file, web site and uninstaller in the  
              ProgramMenuFolder folder, that for an installation for the current user like this maps to CSIDL_PROGRAMS
         -->
         <Directory Id="ProgramMenuFolder">

            <Directory Id="AddInStartMenuFolderId" Name="$(var.DEFAULT_GROUP_NAME)">
           
               <Component Id="HelpFileShortcutComponentId" Guid="$(var.HELP_FILE_SHORTCUT_COMPONENT_GUID)">
              
                  <!-- Create the shortcut to the help file -->
                  <Shortcut Id="HelpFileShortcutId" Name="$(var.APP_NAME)" Description="$(var.APP_NAME)"
                            Target="[INSTALLLOCATION]$(var.HELP_FILE_NAME)" WorkingDirectory="INSTALLLOCATION"/>

                  <!-- Create the shortcut to the web site -->
                  <util:InternetShortcut Id="WebSiteShortcutId" Name="$(var.MY_COMPANY_NAME) Web Site"
                                         Target="$(var.MY_COMPANY_WEB_SITE)" />

                  <!-- Create the shorcut to the uninstaller -->
                  <Shortcut Id="UninstallProduct" Name="Uninstall $(var.APP_NAME)" Target="[SystemFolder]msiexec.exe"
                      Arguments="/x [ProductCode]" Description="Uninstalls $(var.APP_NAME)" />


                  <!-- Ensure that the folder is removed when uninstalling -->
                  <RemoveFolder Id="AddInStartMenuFolderId" On="uninstall"/>
                  
                  
                  <!-- This registry entry used as KeyPath is required to avoid the following warnings:
                  ICE38: Component <x> installs to user profile. It must use a registry key under HKCU as
                         its KeyPath not a file.
                  ICE43: Component HelpFileShortcutComponentId has non-advertised shortcuts. It should use
                         a registry key under HKCU as its KeyPath, not a file.
                  -->
                  <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\HelpFileShortcut" Name="Installed" 
                                 Type="integer" Value="1" KeyPath="yes"/>
                  
               </Component>
               
            </Directory>

         </Directory>
         
      </Directory>

      <!-- Create the tree of features of the setup:
           - A root feature that is always shown (Level=1), expanded, mandatory (can't be absent)
             and that can't be installed on first use (that is, can't be advertised)
           - 3 child optional features
      -->
      <Feature Id="VSCommonFeatureId" Title="$(var.APP_NAME)" Level="1" AllowAdvertise="no"
               Description="Common files of the add-in." Display="expand" Absent="disallow">

         <!-- The root feature includes the license agreement, the help file and its shortcut  -->
         <ComponentRef Id="LicenseAgreementFileComponentId" />
         <ComponentRef Id="HelpFileComponentId" />
         <ComponentRef Id="HelpFileShortcutComponentId" />
         
         <!-- This child feature is the add-in for Visual Studio 2005 -->   
         <Feature Id="VS2005InstallationFeatureId" Title="Visual Studio 2005"
                  Description="Installs the add-in for Visual Studio 2005." Level="1" AllowAdvertise="no">

            <!-- The feature is hidden (Level is set to 0) when Visual Studio 2005 is not installed and
                 it is the first installation (not in maintenance mode)
            -->
            <Condition Level="0">NOT Installed AND NOT VS2005INSTALLATIONFOLDER</Condition>

            <!-- Its components are the add-in dll and the .AddIn XML file for Visual Studio 2005 -->
            <ComponentRef Id="VS2005DllFileComponentId" />
            <ComponentRef Id="VS2005AddInFileComponentId" />
            
         </Feature>

         <!-- This child feature is the add-in for Visual Studio 2008 -->
         <Feature Id="VS2008InstallationFeatureId" Title="Visual Studio 2008"
                  Description="Installs the add-in for Visual Studio 2008." Level="1" AllowAdvertise="no">

            <!-- The feature is hidden (Level is set to 0) when Visual Studio 2008 is not installed and
                 it is the first installation (not in maintenance mode)
            -->
            <Condition Level="0">NOT Installed AND NOT VS2008INSTALLATIONFOLDER</Condition>

            <!-- Its components are the add-in dll and the .AddIn XML file for Visual Studio 2008 -->
            <ComponentRef Id="VS2008DllFileComponentId" />
            <ComponentRef Id="VS2008AddInFileComponentId" />
         
         </Feature>

         <!-- This child feature is the add-in for Visual Studio 2010 -->
         <Feature Id="VS2010InstallationFeatureId" Title="Visual Studio 2010"
                  Description="Installs the add-in for Visual Studio 2010." Level="1" AllowAdvertise="no">

            <!-- The feature is hidden (Level is set to 0) when Visual Studio 2010 is not installed and
                 it is the first installation (not in maintenance mode)
            -->
            <Condition Level="0">NOT Installed AND NOT VS2010INSTALLATIONFOLDER</Condition>

            <!-- Its components are the add-in dll and the .AddIn XML file for Visual Studio 2010 -->
            <ComponentRef Id="VS2010DllFileComponentId" />
            <ComponentRef Id="VS2010AddInFileComponentId" />
        
         </Feature>
      
      </Feature>

      <!-- Custom action to remove the commands of Visual Studio 2005 when uninstalling the add-in -->
      
      <CustomAction Id="RemoveVS2005AddInCommands" Script="vbscript" Execute="deferred" Return="ignore">
         <![CDATA[
            Set dte = CreateObject("VisualStudio.DTE.8.0")
            For Each cmd In dte.Commands
               If InStr(cmd, "$(var.CONNECT_CLASS_FULL_NAME_VS_2005)") <> 0 Then
                  cmd.Delete()
               End If
            Next
            dte.Quit()
         ]]>
      </CustomAction>

      <!-- Custom action to remove the commands of Visual Studio 2008 when uninstalling the add-in -->

      <CustomAction Id="RemoveVS2008AddInCommands" Script="vbscript" Execute="deferred" Return="ignore">
         <![CDATA[
            Set dte = CreateObject("VisualStudio.DTE.9.0")
            For Each cmd In dte.Commands
               If InStr(cmd, "$(var.CONNECT_CLASS_FULL_NAME_VS_2008)") <> 0 Then
                  cmd.Delete()
               End If
            Next
            dte.Quit()
         ]]>
      </CustomAction>

      <!-- Custom action to remove the commands of Visual Studio 2010 when uninstalling the add-in -->

      <CustomAction Id="RemoveVS2010AddInCommands" Script="vbscript" Execute="deferred" Return="ignore">
         <![CDATA[
            Set dte = CreateObject("VisualStudio.DTE.10.0")
            For Each cmd In dte.Commands
               If InStr(cmd, "$(var.CONNECT_CLASS_FULL_NAME_VS_2010)") <> 0 Then
                  cmd.Delete()
               End If
            Next
            dte.Quit()
         ]]>
      </CustomAction>

      <InstallExecuteSequence>
         
         <!-- Execute the defined custom actions to remove the add-in commands from Visual Studio. They must execute when
              all the following conditions are true:
              - The setup has already been run
              - It is not an upgrade
              - Visual Studio is installed
              - The add-in feature state (!feature-state) for the Visual Studio version is installed (3 = INSTALLSTATE_LOCAL). See:
                Conditional Statement Syntax (http://msdn.microsoft.com/en-us/library/aa368012.aspx)
         -->
         <Custom Action="RemoveVS2005AddInCommands"
                 After="RemoveFiles">Installed AND NOT UPGRADINGPRODUCTCODE AND VS2005INSTALLATIONFOLDER 
                                     AND !VS2005InstallationFeatureId=3</Custom>

         <Custom Action="RemoveVS2008AddInCommands"
                 After="RemoveFiles">Installed AND NOT UPGRADINGPRODUCTCODE AND VS2008INSTALLATIONFOLDER 
                                     AND !VS2008InstallationFeatureId=3</Custom>

         <Custom Action="RemoveVS2010AddInCommands"
                 After="RemoveFiles">Installed AND NOT UPGRADINGPRODUCTCODE AND VS2010INSTALLATIONFOLDER 
                                     AND !VS2010InstallationFeatureId=3</Custom>

      </InstallExecuteSequence>
      
      <!-- Use the built-in User interface of the WixUIExtension reference that shows a treeview with features -->
      <UIRef Id="WixUI_FeatureTree" />
      
      <!-- Includes a license agreement step in the setup -->
      <WixVariable Id="WixUILicenseRtf" Value="$(var.LICENSE_AGREEMENT_FILE_NAME)"/>
      
   </Product>

</Wix>

Related articles


Go back to the 'Resources for Visual Studio .NET extensibility' section for more articles like this


Top